Take this code snippet for example:
a = []
for x in range(2):
a.append(lambda: print(x))
print(a[0](), a[1]())
The output is:
1 1
But I expected it to be
0 1
How do I fix this?
Take this code snippet for example:
a = []
for x in range(2):
a.append(lambda: print(x))
print(a[0](), a[1]())
The output is:
1 1
But I expected it to be
0 1
How do I fix this?
Use default arguments:
a = []
for x in range(2):
a.append(lambda x = x: print(x))
print(a[0](), a[1]())
This works because the default value is evaluated when the function is created. Otherwise all lambda functions will point to the last value of x, which was 1.
@sarartur already provided the solution. Here is little more explanation for this behavior.
This is called Late Binding Closures. Quoting from the blog,
Python’s closures are late binding. This means that the values of variables used in closures are looked up at the time the inner function is called.
So here whenever any of the returned functions are called, the value of i
is looked up in the surrounding scope at call time. By then, the loop has completed and i
is left with its final value of 1.
This is happening because your lambda
expressions are printing x
, but x
is being updated by your for
loop, so by the time your lambda
expressions are invoked, x
has finished with a value of 1
because that's the last value in range(2)
.
>>> for num in range(10):
... pass
...
>>> num
9