在这段代码中,lambda 中的 x 指的是 for 语句中的 x。所以y[0]()
返回 2:
x = 0
y = [lambda : x for x in range(3)]
y[0]()
但在这段代码中,lambda 中的 x 指的是全局 x,因此x[0]()
返回全局 x 本身:
x = [lambda : x for x in range(3)]
x[0]()
我想知道为什么 lambda 中的 x 在第一段代码中指的是局部 x 而在第二段代码中指的是全局 x。
在这段代码中,lambda 中的 x 指的是 for 语句中的 x。所以y[0]()
返回 2:
x = 0
y = [lambda : x for x in range(3)]
y[0]()
但在这段代码中,lambda 中的 x 指的是全局 x,因此x[0]()
返回全局 x 本身:
x = [lambda : x for x in range(3)]
x[0]()
我想知道为什么 lambda 中的 x 在第一段代码中指的是局部 x 而在第二段代码中指的是全局 x。
我猜你在 python 2.x 上,在列表理解中,临时变量“泄漏”到命名空间中。您可以在Guido的这篇博文中了解原因。
在 Python 2 中,列表推导将循环控制变量“泄漏”到周围的范围内……这是列表推导的原始实现的产物;多年来,它一直是 Python 的“肮脏小秘密”之一。
这已在 python 3 中修复。
我不确定您为什么将事情与 混淆lambda
,在这里您将在这个更简单的情况下看到相同的行为:
>>> x = 'a'
>>> y = [x for x in 'b','c']
>>> x
'c'
>>> x = [x for x in 'b','c']
>>> x
['b', 'c']
x
指的是x
两段代码中的全局。事实上,在这两段代码中都只有一个全局变量。x
这里没有局部变量,只有全局变量。
在第一个示例中, 的全局值为x
2,因为这是列表推导分配给它的最后一个值。列表推导式将它们的变量泄漏到@wim 所描述的封闭范围中。由于这里的封闭作用域是全局作用域,因此变量x
会泄漏到全局作用域中,覆盖您之前设置的值 0。
在第二个示例中,您创建列表推导式,然后将其值分配给(全局)变量 x。这会覆盖 x 中已经存在的任何内容,因此全局变量 x 的值现在是列表。
在这两种情况下,当您调用列表中的一个函数(任何一个!)时,它都会x
返回. 你可以在这里看到这个:
>>> y = [lambda : x for x in range(3)]
>>> y[0]()
2
>>> x = 88
>>> y[0]()
88
>>> x = [lambda : x for x in range(3)]
>>> y = x
>>> y[0]()
[<function <lambda> at 0x017789B0>,
<function <lambda> at 0x01828DB0>,
<function <lambda> at 0x01828F30>]
>>> x = 88
>>> y[0]()
88
>>> x='a'
>>>x = [lambda : x for x in range(3)]
一旦迭代开始,x
被分配给0
,从返回range()
(并且对'a'的引用被删除)。在最后一次迭代中, 的值x
变为 2,一旦 LC 退出,LC 就被分配给x
,所以现在x
指向 LC。
例子:
>>> [x for x in range(3)]
[0, 1, 2]
>>> x
2
>>> x=[x for x in range(3)]
>>> x
[0, 1, 2]