I have a problem with lambdas in a loop. It is hard to explain the problem so I will show it in a short example:
class TestObj():
def __init__(self, value):
self.value = value
lambdas = []
values_list = [10, 1]
for ele in values_list:
foo = TestObj(ele)
lambdas.append(lambda: foo.value > 5)
print([single_lambda() for single_lambda in lambdas])
as a result of print I get:
[False, False]
Despite I would expect [True, False]. Could you tell me why it does not work? and how Could I get the result that I expected? I only add that lambdas in a loop are required in my code to define formulas(those formulas are a lot and can be much more complex). Those formulas are defined in one place in the application and executed after many lines below the definition. I would be grateful for your help.
Lambdas are evaluated when they are executed.
They are executed when you print them. The only known foo at that time is the one from the last loop. So TestObj(1) is printed twice.
You can verify this by changing your lambda to:
lambdas.append(lambda: id(foo)) # will print the id() of the used foo
You need to "early" bind the foo from the loop to the lambda:
lambdas.append(lambda x = foo: x.value > 5) # bind x to foo from loop, check x.value
Full fix:
class TestObj():
def __init__(self, value):
self.value = value
lambdas = []
values_list = [10, 1]
for ele in values_list:
foo = TestObj(ele)
# use an x and bind it to this loops foo
lambdas.append(lambda x = foo: x.value > 5)
# this is bad btw, use a simple for loop - do not use a list comp to create a list
# simply to print values
print([single_lambda() for single_lambda in lambdas])
Output:
[True, False]
# and for the changed lambda with id() : the same id() twice
See Is it Pythonic to use list comprehensions for just side effects? regarding using list comprehension sideeffects and why its bad.
Related:
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