Python lambdas和范围

时间:2009-12-17 20:02:50

标签: python lambda

给出这段代码:

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

我希望它能打印[0, 1, 2],而是打印[2, 2, 2]。关于lambdas如何使用范围,我是否缺少一些基本的东西?

3 个答案:

答案 0 :(得分:8)

这是Python中的一个常见问题。基本上,范围是这样的:当调用f()时,它将使用x的当前值,而不是lambda形成时x的值。有一个标准的解决方法:

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

使用lambda x = x检索并保存x的当前值。

答案 1 :(得分:5)

x绑定到模块级x(从for循环中遗留下来)。

更清楚一点:

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']

答案 2 :(得分:4)

你知道答案:是的。 ;)然而,请放心,因为这是崭露头角的pythonistas的一个非常普遍的发现。当您定义一个引用该函数内未“创建”的变量的函数或lambda时,它会在变量上创建一个闭包。结果是,在调用函数时获取变量的值,而不是定义时的值。 (你期待后者。)

有几种方法可以解决这个问题。首先是绑定额外的变量:

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]

第二种方式更为正式:

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]