-
-
Notifications
You must be signed in to change notification settings - Fork 275
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
nonlocal variables are included in locals
while global variables not
#2616
Comments
locals
while global variables aren'tlocals
while global variables not
Seems like a bug to me! We should fix this and are open to pull requests :) |
I would try on this. It seems not that hard, since there is The only difference seems to be it requires to go through the tree and find what this nonlocal variable actually refers. Hope I haven't missed anything. |
Including >>> def a():
... x = 1
... def b():
... nonlocal x
... print(locals())
... b()
...
>>> a()
{'x': 1}
>>> def a():
... x = 1
... def b():
... print(locals())
... b()
...
>>> a()
{} |
Ah you are totally right. I should have checked this in the code: ❯ cat /tmp/test.py
def a():
x = 1
y = 2
def b():
global x
nonlocal y
print(locals())
b()
a()
❯ python /tmp/test.py
{'y': 2} Seems like this is actually working as intended? As in, we're mimicking what |
Hard to say! Docstring just says:
From CPython docs for
So does astroid's I also wouldn't want to cause unnecessary churn around emitting/not emitting pylint messages for count of max locals, etc. |
I think why CPython includes those nonlocal variables is because by doing that users can use However we doesn't provide globals in a Meanwhile CPython does not provide usages of the variables, but we do. With the current implemention, we can't find the usgaes inside those nested function: import astroid.nodes
module = astroid.parse(
"""
x1 = 1 # Line 1
def f1(): # Line 2
x2 = 2 # Line 3
def f2(): # Line 4
global x1 # Line 5
nonlocal x2 # Line 6
x1 = 1 # Line 7
x2 = 2 # Line 8
""")
f1 = module.locals["f1"][0]
print(module.locals["x1"]) # [<AssignName.x1 l.2 at 0x2511d5c0170>, <AssignName.x1 l.8 at 0x2511d5c0500>]
print(f1.locals["x2"]) # [<AssignName.x2 l.4 at 0x2511d5c03b0>] And also, it seems that we can't get So will it be a good idea to include both global |
In fact this problem happens in an actual situation when I'm trying to write this PyLint plugin. I want to prevent users from adding type annotation for the same variable duplicately. So I The But I have no idea how to deal with |
That sounds like a way to meet your use case. You might try calling |
I guess I don't think so, I'd rather keep globals and locals separate to avoid astonishing users who expect these variables to track |
Ah there's such a function! But I have to use Anyway that's a great idea and I will use it currently. |
Umm... I think the most convincing reason to do the change is: def f1():
x = 1
def f2():
nonlocal x
x = 2 With the current implemention, |
I guess I wouldn't expect |
Hello! I'm trying
locals
to get the variables (or names) in a function. However I've found that global variables are excluded, while nonlocal variables are here:That's really weird to me. Is it or bug or intentionally designed? If this behavior is expected, what is the recommended solution to exclude those nonlocal variables? (and include global ones?)
I have found #250 , which however was moved from bitbucket in 2015, so I'm not sure whether it is outdated.
Thanks in advance.
The text was updated successfully, but these errors were encountered: