我在Python 3.5.1中尝试了以下代码:
>>> f = {x: (lambda y: x) for x in range(10)}
>>> f[5](3)
9
很明显,这应该返回5
。我不明白其他价值来自哪里,而且我找不到任何东西。
它似乎与引用有关 - 它总是返回f[9]
的答案,这是分配的最后一个函数。
这里的错误是什么,以及如何才能使其正常工作?
答案 0 :(得分:19)
Python范围是词汇。闭包将引用变量的名称和范围,而不是变量的实际对象/值。
每个lambda都会捕获变量x
而不是 x
的值。
在循环结束时,变量x
绑定到9,因此每个lambda将引用此值为9的x
。
为什么@ ChrisP的答案有效:
make_func
强制评估x
的值(因为它已被传递 成功能)。因此,lambda目前的值为x
我们避免上述范围问题。
def make_func(x):
return lambda y: x
f = {x: make_func(x) for x in range(10)}
答案 1 :(得分:6)
以下内容应该有效:
def make_func(x):
return lambda y: x
f = {x: make_func(x) for x in range(10)}
代码中的x
最终会引用最后一个x
值9
,但在我的代码中,它指的是函数范围中的x
。