cell-var-from-loop / W0640ΒΆ
Message emitted:
Cell variable %s defined in loop
Description:
A variable used in a closure is defined in a loop. This will result in all closures using the same value for the closed-over variable.
Problematic code:
def teacher_greeting(names):
greetings = []
for name in names:
def greet():
# do something
print(f"Hello, {name}!") # [cell-var-from-loop]
if name.isalpha():
greetings.append(greet)
for greet in greetings:
# the "name" variable is evaluated when the function is called here,
# which is the last value it had in the loop - "Not-A-Name"
greet()
teacher_greeting(["Graham", "John", "Terry", "Eric", "Terry", "Michael"])
# "Hello, Michael!"
# "Hello, Michael!"
# "Hello, Michael!"
# "Hello, Michael!"
# "Hello, Michael!"
Correct code:
functools.partial.py
:
import functools
def teacher_greeting(names):
greetings = []
for name in names:
if name.isalpha():
# "name" is evaluated when the partial is created here, so this
# does not do lazy evaluation
greetings.append(functools.partial(print, f"Hello, {name}!"))
for greet in greetings:
# `partial`s are called like functions, but you've already passed the
# arguments to them
greet()
teacher_greeting(["Graham", "John", "Terry", "Eric", "Terry", "Michael"])
# "Hello, Graham!"
# "Hello, John!"
# "Hello, Eric!"
# "Hello, Terry!"
# "Hello, Michael!"
new_function.py
:
def teacher_greeting(names):
def greet(name):
# do something
print(f"Hello, {name}!")
for name in names:
if name.isalpha():
# we're passing the value of "name" to the function here
greet(name)
teacher_greeting(["Graham", "John", "Terry", "Eric", "Terry", "Michael"])
# "Hello, Graham!"
# "Hello, John!"
# "Hello, Eric!"
# "Hello, Terry!"
# "Hello, Michael!"
Related links:
Created by the variables checker.