I am hoping the following would produce a list of 3 constant functions taking values 0, 1 and 2:
lis = []
for i in range(3):
lis.append( lambda: i )
But they all end up taking value 2. I would expect deep copying to fix the problem but it doesn't seem to work.
@Boud gave a very good answer explaining why your code doesn't work as you expect it to. Baically, you have to evaluate the value of i
before it is referenced in lambda. Here is a bit hacky way to do it:
lis = []
for i in range(3):
lis.append( lambda i=i: i )
This uses Python's default function arguments' values feature, e.g. in a function one would write:
def f(i=10):
return i
Now, the trick is that an argument has its default value stored at the point when a function (a method, a lambda expression) is created. Thus:
j = 10
def f(i=j):
return i
j = 20
print( f(125) ) # no matter that j has been changed, the output is...
>>> 125
And the same trick applies to lambda. To make it a bit clearer:
lis = []
for j in range(3):
lis.append( lambda i=j: i )
# Calling the lambdas
print(lis[1]())
>>> 1
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