使用lambda函数的字典理解会产生错误的结果

mic*_*bad 21 python lambda dictionary

我在Python 3.5.1中尝试了以下代码:

>>> f = {x: (lambda y: x) for x in range(10)}
>>> f[5](3)
9
Run Code Online (Sandbox Code Playgroud)

很明显这应该回归5.我不明白其他价值来自何处,我无法找到任何东西.

看起来它与引用相关 - 它总是返回答案f[9],这是最后分配的函数.

这里的错误是什么,应该如何做才能使其正常工作?

gni*_*las 20

Python范围是词法.闭包将引用变量的名称和范围,而不是变量的实际对象/值.

会发生什么是每个lambda捕获变量x 而不是x.

在循环结束时,变量x绑定到9,因此每个lambda将引用x其值为9的值.

为什么@ ChrisP的答案有效:

make_func强制x要评估的值(因为它被传递给函数).因此,lambda是用x当前的值制作的,我们避免了上面的范围问题.

def make_func(x):
    return lambda y: x

f = {x: make_func(x) for x in range(10)}
Run Code Online (Sandbox Code Playgroud)

  • 另一个简写是`f = {x :( lambda y,x = x:x)for x in range(10)}`,因为函数默认参数在定义时绑定,所以它们绑定_value_的` x`,而不是_name_`x`. (8认同)
  • 另请参阅[Python 中的常见问题](http://sopython.com/wiki/Common_Gotchas_In_Python) 中的“延迟绑定”段落。 (2认同)

Chr*_*isP 6

以下应该有效:

def make_func(x):
    return lambda y: x

f = {x: make_func(x) for x in range(10)}
Run Code Online (Sandbox Code Playgroud)

x你的代码最终指的是最后一个x值,它是9,但在我它是指x在功能范围.