On Thu, Aug 16, 2018 at 10:33 AM, Jonathan Fine <[email protected]> wrote:
> >> there > >> are times where I have really wanted to access the caller's environment, > >> not the environment where my function was defined. > > > what am I missing? can't you get that by passing locals() in to a > function? > > I think this will fail when values are changed. According to > https://docs.python.org/3/library/functions.html#locals > > The contents of this dictionary should not be modified; changes may not > affect the values of local and free variables used by the interpreter. > and: """ locals() Update and return a dictionary representing the current local symbol table. Free variables are returned by locals() when it is called in function blocks, but not in class blocks. """ it a dictionary *representing* the current local symbol table, so not the actual symbol table -- which surprised me, I thought that is was -- and sometimes it appears to be -- see later example: > To finish, here's an interactive example of changing the value of locals(). > > >>> def f(a=1): loc = locals(); yield loc; yield a > >>> it = f() > >>> ctx = next(it) > >>> ctx > {'a': 1} ## This surprised me. > me too I would have thought "loc" would be in there. > >>> def f(a=1): loc = locals(); yield locals(); yield a > >>> it = f() > >>> ctx = next(it) > >>> ctx > {'a': 1, 'loc': {...}} > now "loc is there" > >>> ctx['a'] = 3 > >>> ctx['loc']['a'] = 5 > >>> next(it) ## Is it 1 or 3 or 5? > 1 ## The value of 'a' hasn't changed. hmm -- made me think that generators are doing something different here -- and indeed they are. If you use regular functions: In [30]: def local_modifying(loc): ...: """ ...: adds a "fred" key to the dict passed in ...: """ ...: print("locals passed in:", loc) ...: loc['fred'] = 5 ...: print("locals after adding", loc) ...: In [31]: def test_locals(): ...: """ ...: a simple local namespace to use ...: """ ...: a = 1 ...: b = 2 ...: local_modifying(locals()) ...: # does "fred" exist? ...: print(locals()) ...: # and we can access it the usual way ...: print("fred:", fred) ...: In [32]: test_locals() locals passed in: {'b': 2, 'a': 1} locals after adding {'b': 2, 'a': 1, 'fred': 5} {'b': 2, 'a': 1, 'fred': 5} fred: 5 It seems you CAN modify the locals dict passed in, and the change will show up in the enclosing scope. But it sounds like that is not guaranteed by the language. -CHB -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception [email protected]
_______________________________________________ Python-ideas mailing list [email protected] https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
