Terry J. Reedy <tjre...@udel.edu> 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 <rep...@bugs.python.org>
<https://bugs.python.org/issue42190>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to