Python 为什么这两个';x';引用不同的变量?

Python 为什么这两个';x';引用不同的变量?,python,Python,在这段代码中,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,在列表理解中,临时变量“泄漏

在这段代码中,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,在列表理解中,临时变量“泄漏”到名称空间中。你可以从中了解为什么

在Python 2中,列表理解“泄漏”了循环控制变量 进入周围的范围。。。这是原作的一件艺术品 清单理解的实施;这是Python的一个“肮脏的” “小秘密”多年

这在Python3中已经修复

我不确定您为什么要将事情与
lambda
混淆,在这里,您将在这个简单的案例中看到相同的行为:

>>> x = 'a'
>>> y = [x for x in 'b','c']
>>> x
'c'
>>> x = [x for x in 'b','c']
>>> x
['b', 'c']
迭代一开始,
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]

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
>y=[lambda:x表示范围(3)内的x]
>>>y[0]()
2.
>>>x=88
>>>y[0]()
88
>>>x=[lambda:x表示范围(3)内的x]
>>>y=x
>>>y[0]()
[,
,
]
>>>x=88
>>>y[0]()
88

由于范围的原因。。。请看:我个人更喜欢“泄漏”实现,因为它在功能上与for循环相同,一旦完成,它的控制变量也将保留在作用域中。我想大家的看法不尽相同。。我不喜欢它,可以想到没有有效的用例来“泄漏”,我确实被它刺痛过一次。我认为删除行为是正确的,因为我认为列表理解是一个逻辑单元,控件只是一个自由变量,而不是一个定义,类似于谓词演算。是的,我当然理解并理解其中的原因。
>>> 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