Peter Otten於 2019年9月20日星期五 UTC+8下午3時31分48秒寫道: > jf...@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. -- https://mail.python.org/mailman/listinfo/python-list