2016-04-23 31 views
16

我尝试在Python 3.5.1以下代码:与lambda函数解释的理解给出了错误的结果

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

很明显,这应该返回5。我不明白其他价值来自哪里,我无法找到任何东西。

它看起来像是与参考相关的东西 - 它总是返回f[9]的答案,这是分配的最后一个函数。

这里有什么错误,应该怎么做才能正常工作?

回答

14

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

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

在循环变量x势必9月底,因此每个拉姆达将把这个x,其值是9

为什么@ ChrisP的回答工作:

make_func强制对x的值进行评估(因为它将 传递给函数)。因此,拉姆达的值为x,目前为 ,我们避免了上述范围问题。

def make_func(x): 
    return lambda y: x 

f = {x: make_func(x) for x in range(10)} 
+7

一种替代速记将'F = {X:(拉姆达Y,X = X:X),用于在范围X(10)}',因为函数默认参数在定义的时间限制,所以他们会绑定'x'的_value_,而不是_name_'x'。 – ShadowRanger

+0

这可能听起来像一个非常愚蠢的问题(我对lambda不太熟悉),但make_func(x)如何工作?我可以想象f [5](3)意味着 - > f = {5:make_func(5)}。那么make_func(5)(3)如何等于5? – Adib

+1

词典理解使得整数的字典键成为函数的值。 f [5]返回键入5的字典中的值,它恰好是函数lambda:x。请注意,lambda忽略在(y)中传递的任何内容,并始终返回x。这就是为什么lambda将返回5或9(由于上述问题)。 – gnicholas

6

下面应该工作:

def make_func(x): 
    return lambda y: x 

f = {x: make_func(x) for x in range(10)} 

x在你的代码最终指的是最后x价值,这是9,但在我它是指x的功能范围。