I was surprised that you cannot access dynamically created local variables even though they exist.
Looks like the local dictionary still exists. Just that whether accessing a local variable looks it up in the local or global dictionary is determined at compile time.
> PEP 667: The locals() builtin now has defined semantics when mutating the returned mapping. Python debuggers and similar tools may now more reliably update local variables in optimized scopes even during concurrent code execution.
> To ensure debuggers and similar tools can reliably update local variables in scopes affected by this change, FrameType.f_locals now returns a write-through proxy to the frame’s local and locally referenced nonlocal variables in these scopes
Interesting. As I understand it, it will not affect my example:
def f():
exec('y = 7') # will still create a local variable
print(locals()['y']) # will still print this local variable
print(y) # will still try to access a global variable 'y'
Python 3.12.2 ...
Type "help", "copyright", "credits" or "license" for more information.
>>> def f():
... exec('y = 7') # will still create a local variable
... print(locals()['y']) # will still print this local variable
... print(y) # will still try to access a global variable 'y'
...
>>> f()
7
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in f
NameError: name 'y' is not defined
Messing with locals has been a long-time danger zone. I don't know how it is supposed to interact with exec - another danger zone - and I don't know enough about the changes in 3.13 to know if it's resolved.
https://x.com/marekgibney/status/1817495719520940236
I was surprised that you cannot access dynamically created local variables even though they exist.
Looks like the local dictionary still exists. Just that whether accessing a local variable looks it up in the local or global dictionary is determined at compile time.