exec and globals and locals ...
jfong at ms4.hinet.net
jfong at ms4.hinet.net
Fri Sep 20 04:28:25 EDT 2019
Peter Otten於 2019年9月20日星期五 UTC+8下午3時31分48秒寫道:
> 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.
Hmm... exec() seems follow a more "LEGB" rule:-)
Thank you.
More information about the Python-list
mailing list