Python knows several kinds of scope: module global
, function local, nonlocal
closures, class body. Notably, scope resolution is defined statically at byte code compile time – most importantly, whether names refer to local/nonlocal or global scope cannot be changed.
Of these scopes, only global scope is guaranteed to behave similar to a dict
, and as such writeable. The local/nonlocal scope is generally not writeable, and new variables cannot be added to it.
exec
will write to the global scope if locals is not passed in; globals must then explicitly be set to its default of globals()
.
def func():
exec("a='exec'", globals()) # access only global scope
print(a)
a = 'global'
func() # prints exec
However, once a name is local to a function, exec
cannot modify it.
def func():
a = 'local' # assignment makes name local
exec("a='exec global'", globals())
exec("a='exec locals'", globals(), locals())
print(a)
a = 'global'
func() # prints local
While a dict
-like representation of local/nonlocal scope exists, the interpreter is not required to honour changes to it.
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. Note that at the module level, locals() and globals() are the same dictionary.
Note: The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.
Even though exec
does take locals as a dict
, these are not treated like function locals/nonlocals. Attempts to modify the default locals (the result of locals()
) are not defined.
... If globals and locals are given, they are used for the global and local variables, respectively. If provided, locals can be any mapping object. Remember that at module level, globals and locals are the same dictionary. If exec gets two separate objects as globals and locals, the code will be executed as if it were embedded in a class definition.
Note: The default locals act as described for function locals()
below: modifications to the default locals dictionary should not be attempted. ...