Terry J. Reedy <[email protected]> added the comment:
exec with different global and local dicts is most like executing code in a
class definition, where locals is different from globals. But mimicking your
exec with an actual class statement does not produce the same result.
>>> gdict = {}
>>> class C:
x = 1
def f(): global x
>>> gdict
{}
>>> C.x
1
# To continue, I reproduced the behavior in 3.10.
>>> ldict = {}
>>> exec('''
x = 1
def f(): global x''', gdict, ldict)
>>> 'x' in gdict
True
# And that putting x in gdict required the global declaration.
>>> gdict = {}
>>> exec('''
x = 1
def f(): pass''', gdict, ldict)
>>> 'x' in gdict
False
>>> 'x' in ldict
True
This seems like a bug to me too. The change is in the bytecode, not the
subsequent execution thereof.
>>> dis.dis('x = 1')
1 0 LOAD_CONST 0 (1)
2 STORE_NAME 0 (x)
...
# Ditto if add '\ndef f(): pass', but here is the test case.
>>> dis.dis('x = 1\ndef f(): global x')
1 0 LOAD_CONST 0 (1)
2 STORE_GLOBAL 0 (x)
...
# Same result for 'global x; x = 1', but 'x = 1; global x' raises
SyntaxError: name 'x' is assigned to before global declaration
The change is inconsequential when locals is globals, but not when not.
----------
nosy: +gvanrossum, lys.nikolaou, pablogsal, terry.reedy
stage: -> needs patch
versions: +Python 3.10, Python 3.9
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue42190>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com