-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Warning possibly-undefined-variable
if a for loop variable that was not defined prior to the loop is accessed out of its intended scope
#5146
Comments
A check that warn when you're accessing a variable outside of its scope would be useful. But the fix is to not do that, adding a del make the code worse. |
How so? I agree that code like this should be avoided altogether by splitting it into functions or something but is there a reason why using |
In essence this would mean you always have to put a Consider the following: What would be the next step? Now that you changed it, the But if you are afraid of that, you might also be afraid that accessing loop variables after the loop finished could happen anywhere in your code base. |
To add to that, it's just the way python works: adding a del after every for loop would clutter the code (possibly have performance implication too) when the easy fix is to not use variables out of their scope. . Asking user to do that would be a colossal waste of resources too. How many for loops where made in Python in 30 years? If applied blindly on every Python code ever made this check would suggest adding probably trillions of line of del statement to perfectly fine code. So, if something need to change regarding the possibility to shoot oneself in the foot by accessing for loop variable out of scope like this, it should be in Python design itself. |
So more like for name in names:
print(name)
send_message(name) # sus alert! Reused variable from loop |
Here's an article I found interesting which point out that there's also possible complications to using del (exceptions handling), provide historical context supposedly from Guido but without actual source or I would have linked that, and show some useful pattern that can be used because of this, like: for i in somegenerator():
if isinteresing(i):
break
dostuffwith(i) Or for i, item in enumerate(somegenerator()):
dostuffwith(i, item)
print('The loop executed {0} times!'.format(i+1)) |
reused-loop-variable-out-of-scope
if a variable is accessed out of its intended scope
The examples you provide are why I would say a for loop doesn’t necessarily imply an “intended scope”. I think this warning will flag perfectly valid code and will therefore become quite controversial. As it also doesn’t provide any real performance benefit I think this should be an optional warning, if it should be a warning at all. |
In my first comment I initially had a sentence also saying that this would be perfectly valid code, but deleted it shortly after. |
I like that solution! Warning because of potential undefinition seems much more logical than for using “semi out of scope” variable names. |
Ok, so it seems a reasonable resolution for this issue would be to add an optional extension for the opinionated With the following functional tests:
|
I would only vote for the The first functional test for The second functional test for |
I like your argument.
|
If you want to be explicit that you want the value available outside the loop, you could use something like:
But that doesn't solve the issue around whether the second loop expected I agree with DudeNr33 (and pycharm) that the warning should only occur when the variable has not been assigned before the loop, so could be undefined after. |
reused-loop-variable-out-of-scope
if a variable is accessed out of its intended scopepossibly-undefined-variable
if a for loop variable that was not defined prior to the loop is accessed out of its intended scope
Ah, I thought those functional tests were "standalone" examples. def find_suitable_candidate():
j = None
for j in list_of_most_probable_candidates:
if is_suitable(j):
break
if j:
return j
for j in list_of_less_probable_candidates:
if is_suitable(j) and some_other_criterion(j):
break
return j While this code is far from perfect and could be simplified, this is a case where accessing As for the for i in [1, 2, 3]:
print(i)
print("The last number was:", i). # won't complain As soon as the iterable is not directly defined in the |
Closing as pylint complain if the list is empty or can be empty. for value in [1, 2, 3]:
print(value)
for other_value in [2, 3, 4]:
print(value) # no warning
for value_2 in []:
print(value)
for other_value in [2, 3, 4]:
print(value_2) # [undefined-loop-variable]
def print_names(names):
for name in names:
print(name)
send_message(name) # [undefined-loop-variable]
def send_message(i):
print(i) Result:
I think this is very close to the optimal in term of false positive/false negative. Thanks to @jacobtylerwalls for making this check very good in countless MR ! |
Current problem
an annoying feature in python is how variables are still in scope when you wouldn't expect them to be
Desired solution
a rule that warns when a variable is being accessed outside of the "scope" where it was defined, suggesting that you
del
the variable. in the example above, it could suggest the following fix:Additional context
No response
The text was updated successfully, but these errors were encountered: