Hey @grok, there was something wrong with exec("a=1"), maybe the "a" turned into global or something?
Thought for 45s
Yes, you're spot on that there's a gotcha with exec("a=1")—it behaves unexpectedly (and frustratingly) when used inside a function, and it often feels like the assignment "disappears" or ends up in the wrong scope. This isn't a bug, but a deliberate (if quirky) design choice in Python tied to how local variables are optimized for speed. Let me break it down with examples, explain why it happens, and suggest workarounds.The Issue in a NutshellAt the global/module level (e.g., in a script or interactive shell outside a function), exec("a=1") works fine: it assigns a=1 to the global namespace, and you can access it directly.
Inside a function, things go sideways:If a is already declared as a local (e.g., a = 0 before the exec), the assignment updates the locals() dictionary temporarily, but direct references to a in the function still see the old value. The change is "lost" for the rest of the function.
If a hasn't been declared locally yet, exec("a=1") sets it in locals(), but trying to access a directly raises a NameError (Python treats it as a global lookup, which fails).
In neither case does it automatically become a global unless you explicitly tell it to (more on that below). Your hunch about "global or something" is close but not quite—it ends up in limbo in the locals() dict without affecting normal variable access.
This stems from Python's bytecode optimization: Local variables in functions are stored in fast-access "slots" compiled at function-definition time. exec runs dynamic code that doesn't know about those slots, so it can't update them. Instead, it fiddles with the locals() dict (a proxy/snapshot), which the interpreter ignores for direct access.
Hey @grok, there was something wrong with exec("a=1"), maybe the "a" turned into global or something?
Thought for 45s
Yes, you're spot on that there's a gotcha with exec("a=1")—it behaves unexpectedly (and frustratingly) when used inside a function, and it often feels like the assignment "disappears" or ends up in the wrong scope. This isn't a bug, but a deliberate (if quirky) design choice in Python tied to how local variables are optimized for speed. Let me break it down with examples, explain why it happens, and suggest workarounds.The Issue in a NutshellAt the global/module level (e.g., in a script or interactive shell outside a function), exec("a=1") works fine: it assigns a=1 to the global namespace, and you can access it directly. Inside a function, things go sideways:If a is already declared as a local (e.g., a = 0 before the exec), the assignment updates the locals() dictionary temporarily, but direct references to a in the function still see the old value. The change is "lost" for the rest of the function. If a hasn't been declared locally yet, exec("a=1") sets it in locals(), but trying to access a directly raises a NameError (Python treats it as a global lookup, which fails).
In neither case does it automatically become a global unless you explicitly tell it to (more on that below). Your hunch about "global or something" is close but not quite—it ends up in limbo in the locals() dict without affecting normal variable access.
This stems from Python's bytecode optimization: Local variables in functions are stored in fast-access "slots" compiled at function-definition time. exec runs dynamic code that doesn't know about those slots, so it can't update them. Instead, it fiddles with the locals() dict (a proxy/snapshot), which the interpreter ignores for direct access.