[Python-ideas] Jump to function as an an alternative to call function

Chris Barker chris.barker at noaa.gov
Thu Aug 16 15:32:54 EDT 2018


On Thu, Aug 16, 2018 at 10:33 AM, Jonathan Fine <jfine2358 at gmail.com> 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

Chris.Barker at noaa.gov
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180816/5cf5c682/attachment.html>


More information about the Python-ideas mailing list