exec and globals and locals ...
Peter Otten
__peter__ at web.de
Fri Sep 20 03:31:09 EDT 2019
jfong at ms4.hinet.net wrote:
>>>> x = 3
>>>> def foo():
> ... exec("print(globals(), locals()); x = x + 1; print(globals(),
> locals())") ...
>>>> foo()
> {'foo': <function foo at 0x021C3468>, '__package__': None, '__builtins__':
> {<module 'builtins' (built-in)>, '__loader__': <class
> {'_frozen_importlib.BuiltinImporter'>, '__doc__': None, '__name__':
> {'__main__', '__spec__': None, 'x': 3} {} 'foo': <function foo at
> {0x021C3468>, '__package__': None, '__builtins__': <module 'builtins'
> {(built-in)>, '__loader__': <class '_frozen_importlib.BuiltinImporter'>,
> {'__doc__': None, '__name__': '__main__', '__spec__': None, 'x': 3} {'x':
> {4}
>>>> def goo():
> ... print(globals(), locals())
> ... x = x + 1
> ... print(globals(), locals())
> ...
>>>> goo()
> {'foo': <function foo at 0x021C3468>, '__package__': None, '__builtins__':
> {<module 'builtins' (built-in)>, '__loader__': <class
> {'_frozen_importlib.BuiltinImporter'>, '__doc__': None, '__name__':
> {'__main__', '__spec__': None, 'goo': <function goo at 0x021C3420>, 'x':
> {3} {}
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> File "<stdin>", line 3, in goo
> UnboundLocalError: local variable 'x' referenced before assignment
>>>>
>
> Can't figure out what makes it different:-(
(0) exec() and class definitions use the LOAD_NAME opcode which looks into
the local namespace first and falls back to the global namespace. Therefore
x = x may look up a global x and assign to a local one
The function body uses either
(1) if there is a name binding operation (assignment, augmented assignment,
def, ...) LOAD_FAST which only looks into the local namespace. Thus
x = x will only succeed if x is already defined in the local namespace.
(2) if there is no binding operation (name appears in an expression, x[...]
= ... or attribute assignment) LOAD_GLOBAL which only looks into the local
namespace.
Your first example is case 0, your second is case 1.
More information about the Python-list
mailing list