[Tutor] eval use (directly by interpreter vs with in a script)

eryksun eryksun at gmail.com
Mon Nov 3 01:14:58 CET 2014


On Sun, Nov 2, 2014 at 3:07 PM, Peter Otten <__peter__ at web.de> wrote:
> Inside a function there is no direct way to get access to the local
> namespace used by exec().

Indeed, exec() can't create new function locals, or even update the
values of existing function locals.

Another option for indirect access is to use the locals() dict. A bare
exec() uses the current locals(), i.e. exec(obj) is equivalent to
exec(obj, globals(), locals()).

    def f():
        exec('x = 42')
        print(locals()['x'])

    >>> f()
    42

This doesn't contradict the fact that exec() can't create new
function-scope locals. For the frame of a function call, this dict is
a legacy namespace. In CPython, a function scope is optimized [*] to
instead use the frame's array of "fast locals".

Updating a function's legacy locals doesn't affect its fast locals.
Instead, calling locals() merges the fast locals into the dict and
returns it as a snapshot.

    def f():
        x = 0
        f_locals = locals()
        f_locals['x'] = 42
        print(x, f_locals['x'])
        locals() # update the snapshot
        print(x, f_locals['x'])

    >>> f()
    0 42
    0 0

[*] OTOH, the code for a module or class body is unoptimized. For a
module body, globals and locals are the same dict, which is the module
object's __dict__. The locals dict of a class body is passed to the
metaclass __new__ constructor (usually type.__new__), which copies it
as the class object's __dict__.


More information about the Tutor mailing list