- nie 14 czerwca 2020
- Programming
- #python, #python-quirks
Lambda's variables are evaluated during it's execution, not when it's declared
Consider this snippet:
functions = []
for x in range(1, 11):
functions.append(lambda : print(x))
for f in functions:
f()
When I first wrote some code like that, I thought the output would be like that:
1
2
3
.
.
10
Instead it printed '10' ten times:
10
10
.
.
10
The reason for that is simple: the variables we use in lambdas are evaluated only when the lambda is called.
Python will call each lambda, and when it encounters the x
variable, it will just take the object that the x
is referencing. And because we call lambdas after we iterated over range(1, 11)
the x
variable will be 10 each time.
Dirty solution
In Python the keyword arguments are evaluated when the function is loaded, not when it is called. We can use this fact to get the result we want:
functions = []
for x in range(1, 11):
functions.append(lambda tmp=x: print(tmp))
for f in functions:
f()
The result:
1
2
3
.
.
10
This look a little bit weird, and I think I have never seen code like that - that's why I called it a dirty solution. A better solution would be to probably not use lambdas at all and use closures instead.
Better solution
functions = []
def some_clever_name(tmp):
def wrapped():
print(tmp)
return wrapped
for x in range(1, 11):
functions.append(some_clever_name(x))
for f in functions:
f()
And now we are talking! This works because when some_clever_name
function is called - Python creates a local variable
tmp
(that references the same object that x
) which is later used when wrapped
function is called.