Lambda with different expression returns same output

Question:

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?

Asked By: Avi Shah

||

Answers:

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.

Answered By: sarartur

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
Answered By: ddejohn

@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.

Answered By: Abdul Niyas P M
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.