Today I explored a weird behavior of Python. An example:
closures = []
for x in [1, 2, 3]:
# store `x' in a "new" local variable
var = x
# store a closure which returns the value of `var'
closures.append(lambda: var)
for c in closures:
print(c())
The above code prints
3
3
3
But I want it to print
1
2
3
I explain this behavior for myself that var
is always the same local variable (and python does not create a new one like in other languages). How can I fix the above code, so that each closure will return another value?
The easiest way to do this is to use a default argument for your lambda, this way the current value of x
is bound as the default argument of the function, instead of var
being looked up in a containing scope on each call:
closures = []
for x in [1, 2, 3]:
closures.append(lambda var=x: var)
for c in closures:
print(c())
Alternatively you can create a closure (what you have is not a closure, since each function is created in the global scope):
make_closure = lambda var: lambda: var
closures = []
for x in [1, 2, 3]:
closures.append(make_closure(x))
for c in closures:
print(c())
make_closure()
could also be written like this, which may make it more readable:
def make_closure(var):
return lambda: var
You can't create a new variable in the local scope inside the loop. Whatever name you choose, your function will always be a closure over that name and use its most recent value.
The easiest way around this is to use a keyword argument:
closures = []
for x in [1, 2, 3]:
closures.append(lambda var=x: var)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With