-
-
Notifications
You must be signed in to change notification settings - Fork 31k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
locals() in a module or class scope comprehension does not include the iteration var(s) since 3.12b1 #105340
Comments
With PEP-709, list comprehensions do not have their own stack. This affects top-level sentences. |
Thanks for the reference. I do think the current behavior violates the PEP, which indicates that "locals() includes outer variables", suggesting that locals() would continue to include inner variables, and confirmed by the example where "under this PEP", In my example above, |
The correct thing seems to be something like locals() == {**globals(), "name": ... } |
This seems to me to be more correct than the alternative (replacing the existing name for the duration of the list comprehension) in particular because globals are visible to outside code. Is there a practical problem with not including the loop variable in the locals() at the global level? |
I'm not sure I understand the question or if it was even directed at me. The problem I see is that it's no longer possible to reference
Any code that depends on locals actually representing the local variables will fail. I linked to the code that started failing as a result of this change... but as I mentioned, that code used a legacy construct that's superseded by f-strings. I'm not yet aware of any other practical uses. In general, this change feels like a breaking change deserving of a deprecation period. |
I do agree that this is a behavior change that wasn't called out in PEP 709 and that we didn't realize would be an issue before. PEP 709 says that locals() now includes the variables from the outer frame. That's true in functions, where locals() now includes both outer and comprehension-local variables, but in module and class scopes, it now includes only the outer variables.
And that can indeed break code like the code @jaraco linked above. To fix it, I wonder if inside the implementation of |
Yes, the lack of I'm traveling this week but will be able to look into possible fixes here more closely next week. It's tricky because we can't actually add the key to the module globals (or class "locals") dictionary without potentially stomping on an existing outer-scoped variable, which would be much worse. There may be potential band-aids where |
) * pythongh-105340: include hidden fast-locals in locals() (cherry picked from commit 104d7b7) Co-authored-by: Carl Meyer <carl@oddbird.net>
In Python 3.11, inside a comprehension,
locals()
was bound to the scope of the comprehension:But since 3.12b1,
locals()
isglobals()
:May be related to #105256.
Discovered in this job, triggered by this code (which I intend to update not to use
locals()
).Is this change intentional?
Linked PRs
The text was updated successfully, but these errors were encountered: