开发者

Python lambdas and scoping [duplicate]

This question already has answers here: Creating functions (or lambdas) in a loop (or comprehension) (6 answers) Closed 4 months ago.

Given this snippet o开发者_StackOverflow社区f code:

funcs = []
for x in range(3):
    funcs.append(lambda: x)
print [f() for f in funcs]

I would expect it to print [0, 1, 2], but instead it prints [2, 2, 2]. Is there something fundamental I'm missing about how lambdas work with scope?


This is a frequent question in Python. Basically the scoping is such that when f() is called, it will use the current value of x, not the value of x at the time the lambda is formed. There is a standard workaround:

funcs = []
for x in range(10):
funcs.append(lambda x=x: x)
print [f() for f in funcs]

The use of lambda x = x retrieves and saves the current value of x.


x is bound to the module-level x (which is left over from the for loop).

A little clearer:

funcs = []

for x in range(10):
    funcs.append(lambda: x)

x = 'Foo'

print [f() for f in funcs]

# Prints ['Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo']


You know the answer: yes. ;) Take comfort, however, as this is a very common discovery for budding pythonistas. When you define a function or lambda that references variables not "created" inside that function, it creates a closure over the variables. The effect is that you get the value of the variable when calling the function, not the value at definition time. (You were expecting the latter.)

There are a few ways to deal with this. First is binding extra variables:

funcs = []
for x in range(10):
    funcs.append(lambda x=x: x)
print [f() for f in funcs]
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

The second way is a little more formal:

from functools import partial
funcs = []
for x in range(10):
    funcs.append(partial(lambda x: x, x))
print [f() for f in funcs]
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜