Questions about `locals` builtin

Chris Angelico rosuav at gmail.com
Wed Feb 28 02:01:42 EST 2018


On Tue, Feb 27, 2018 at 5:55 AM, Kirill Balunov <kirillbalunov at gmail.com> wrote:
> 2. The documentation has a note that "The contents of this dictionary
> should not be modified". Which implies that it is a read only mapping. So
> the question why it is `dict` instead of `types.MappingProxyType`?

A dict is smaller and faster. In some Python implementations, locals()
returns an actual dictionary of the actual locals; to construct a
proxy would be a waste of effort, and to have the internal locals use
a proxy is also a complete waste. Python tends not to enforce rules
that won't actually cause a crash, so it's simpler and more efficient
to give you a real dictionary and say "changing this might not do what
you think it does".

> 3. There is one more moment: local variables had been determined when
> function was compiled. But `locals` returns _some_ current runtime copy. I
> find this also confusing:
>
>
>>>> def func1():
>
>     loc = locals()
>
>     b = 12
>
>     return loc
>
>
>>>> def func2():
>
>     b = 12
>
>     loc = locals()
>
>     return loc
>
>
>>>> func1()
> { }
>>>> func2()
> {'b': 12}

The values of those locals is calculated at run-time, but the set of
names is not. If a name has not been bound, it's still flagged as
"local", but it doesn't appear in locals(), because there's no
corresponding value. So if "b" is not in locals(), attempting to
access the variable named b will raise UnboundLocalError.

Dictionaries don't have a way to say "this thing exists but has no
value"; so this says "this thing doesn't exist", which is close
enough. If you really want a list of ALL the local names in a
function, you can look at its __code__ object, which has a tuple of
variable names:

print(func1.__code__.co_varnames)

That information is static to the function, as it is indeed determined
when the function is compiled.

ChrisA



More information about the Python-list mailing list