exec() an locals() puzzle

Eryk Sun eryksun at gmail.com
Wed Jul 20 14:54:06 EDT 2022


On 7/20/22, george trojan <george.trojan at gmail.com> wrote:
>
> 1. This works as I expect it to work:
>
> def f():
>     i = 1
>     print(locals())
>     exec('y = i; print(y); print(locals())')
>     print(locals())
>     exec('y *= 2')
>     print('ok:', eval('y'))
> f()

In CPython, the locals of a function scope (as opposed to a class
scope or module scope) are optimized by storing them in an array in
the current frame. locals(), however, always returns the non-optimized
locals mapping of the current frame, i.e. the value of
sys._getframe(0).f_locals. In the case of optimized locals, the
locals() call first updates this dict with a snapshot of the current
values of local variables. This is useful for introspection, but
modifying the snapshot cannot extend or modify the optimized local
variables of the function scope.

exec() and eval() default to using the global and local variable
mappings that are returned by globals() and locals(). This allows them
to access the snapshot of the containing function's optimized locals,
but they can't extend or modify the function's optimized locals. At
most they can add dynamic locals to the snapshot, as used by
subsequent calls to locals(), exec() and eval().


More information about the Python-list mailing list