List comprehension variable used in enclosing scopeΒΆ
ID: py/leaking-list-comprehension
Kind: problem
Severity: warning
Precision: very-high
Tags:
- portability
- correctness
Query suites:
- python-security-and-quality.qls
Click to see the query in the CodeQL repository
In Python 2 list comprehensions are evaluated in the enclosing scope, which means that the iteration variable of a list comprehension is visible outside of the list comprehension. In Python 3 the iteration variable is no longer visible in the enclosing scope.
Code that uses the value of a list comprehension iteration variable after the list comprehension has finished will behave differently under Python 2 and Python 3.
RecommendationΒΆ
Explicitly set the variable in the outer scope to the value that it would have held when run under Python 2. Then rename the list comprehension variable for additional clarity.
ExampleΒΆ
In this example, x is initially assigned the value of 3. In Python 3, x will be unchanged as the list comprehension is evaluated in its own scope. In Python 2, evaluation of the list comprehension occurs in the scope of two_or_three, setting x to 2.
def two_or_three():
x = 3
[0 for x in range(3)]
return x # Will return 2 in Python 2 and 3 in Python 3.
print(two_or_three())
The following example is the same code as above, but the list comprehension variable is renamed to ensure it does not overwrite x.
def just_three():
x = 3
[0 for y in range(3)]
return x # Will return always return 3.
print(just_three())
ReferencesΒΆ
Python Tutorial: List Comprehensions.
The History of Python: From List Comprehensions to Generator Expressions.
Python Language Reference: List displays.