grześ
grześ

Reputation: 497

Invalid closure in Python's lambda function

Consider this short code snippet:

class X:
    pass

xs = []
for s in ("one", "two", "three"):
    x = X()
    x.f = lambda: print(s)
    xs.append(x)

for x in xs:
    x.f()

It outputs:

three
three
three

I thought the result should be like this instead:

one
two
three

Why is that not the actual result?

Upvotes: 3

Views: 54

Answers (2)

MartenCatcher
MartenCatcher

Reputation: 2887

It happens because the s variable is a reference, not a value. And the value by reference will be resolved when it will be called, not created. To resolve the value in the creation time use the default argument.

lambda s=s: print(s)

Upvotes: 2

Praveenkumar
Praveenkumar

Reputation: 2182

Your lambda function holds reference to s, hence the last assigned value to s is printed when called outside that for loop. Try the below code for your expected behaviour. Here a copy of that existing reference s is created in v as function argument and that value is printed inside the function f.

class X:
    pass

xs = []
for s in ("one", "two", "three"):
    x = X()
    def f(v=s): print(v)
    x.f = f
    xs.append(x)

for x in xs:
    x.f()

Output:

one
two
three

Upvotes: 2

Related Questions