为什么这两个'x'指的是不同的变量?

时间:2022-09-06 16:32:40

In this code, the x in the lambda refers to the x in the for statement. So y[0]() returns 2:

在此代码中,lambda中的x指的是for语句中的x。所以y [0]()返回2:

x = 0
y = [lambda : x for x in range(3)]
y[0]()

But in this code, the x in the lambda refers to global x, so x[0]() returns global x itself:

但是在这段代码中,lambda中的x指的是全局x,所以x [0]()返回全局x本身:

x = [lambda : x for x in range(3)]
x[0]()

I want to know why the x in the lambda refers to the local x in the first piece of code but global x in the second piece of code.

我想知道为什么lambda中的x指的是第一段代码中的局部x,而第二段代码中的全局x。

3 个解决方案

#1


5  

x refers to the global x in both pieces of code. Indeed, there is nothing but a global x in both pieces of code. There are no local variables here, only global variables.

x指的是两段代码中的全局x。实际上,在两段代码中只有一个全局x。这里没有局部变量,只有全局变量。

In the first example, the global value of x is 2, because that was the last value assigned to it by the list comprehension. List comprehensions leak their variables into the enclosing scope as described by @wim. Since the enclosing scope here is the global scope, the variable x is leaked into global scope, overwriting the value 0 that you set earlier.

在第一个示例中,x的全局值为2,因为这是列表推导分配给它的最后一个值。列表推导将其变量泄漏到@wim所描述的封闭范围中。由于此处的封闭范围是全局范围,因此变量x将泄漏到全局范围,覆盖您之前设置的值0。

In the second example, you create the list comprehension, but then assign its value to the (global) variable x. This overwrites whatever was already in x, so the value of the global variable x is now the list.

在第二个示例中,您创建列表推导,但随后将其值分配给(全局)变量x。这会覆盖x中已有的内容,因此全局变量x的值现在是列表。

In both cases, when you call one of the functions in the list (any one!), it returns the current value of x. You can see this here:

在这两种情况下,当您调用列表中的一个函数(任何一个!)时,它将返回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

#2


6  

I guess you are on python 2.x, where in a list comprehension, the temporary variable 'leaks' into the namespace. You can read about why in this blog post from Guido.

我猜你是在python 2.x上,在列表解析中,临时变量'泄漏'进入命名空间。您可以在Guido的这篇博客文章中了解原因。

In Python 2, the list comprehension "leaks" the loop control variable into the surrounding scope ... This was an artifact of the original implementation of list comprehensions; it was one of Python's "dirty little secrets" for years.

在Python 2中,列表推导将循环控制变量“泄漏”到周围的范围内......这是列表推导的原始实现的工件;多年来它一直是Python的“肮脏的小秘密”之一。

This has been fixed in python 3.

这已在python 3中修复。

I'm not sure why you are confusing things with the lambda, here you will see the same behaviour in this simpler case:

我不确定你为什么要把这些东西与lambda混淆,在这个简单的例子中你会看到相同的行为:

>>> x = 'a'
>>> y = [x for x in 'b','c']
>>> x
'c'
>>> x = [x for x in 'b','c']
>>> x
['b', 'c']

#3


2  

>>> x='a'
>>>x = [lambda : x for x in range(3)]

as soon as the iteration starts the x gets assigned to 0, returned from range()(and and reference to 'a' is removed). In the final iteration the value of x becomes 2, and as soon as the LC exits the LC gets assigned to x, so now x points to the LC.

一旦迭代开始,x被赋值为0,从range()返回(并删除对'a'的引用)。在最后的迭代中,x的值变为2,并且一旦LC退出,LC就被分配给x,所以现在x指向LC。

example:

例:

>>> [x for x in range(3)]
[0, 1, 2]
>>> x     
2
>>> x=[x for x in range(3)]
>>> x
[0, 1, 2]

#1


5  

x refers to the global x in both pieces of code. Indeed, there is nothing but a global x in both pieces of code. There are no local variables here, only global variables.

x指的是两段代码中的全局x。实际上,在两段代码中只有一个全局x。这里没有局部变量,只有全局变量。

In the first example, the global value of x is 2, because that was the last value assigned to it by the list comprehension. List comprehensions leak their variables into the enclosing scope as described by @wim. Since the enclosing scope here is the global scope, the variable x is leaked into global scope, overwriting the value 0 that you set earlier.

在第一个示例中,x的全局值为2,因为这是列表推导分配给它的最后一个值。列表推导将其变量泄漏到@wim所描述的封闭范围中。由于此处的封闭范围是全局范围,因此变量x将泄漏到全局范围,覆盖您之前设置的值0。

In the second example, you create the list comprehension, but then assign its value to the (global) variable x. This overwrites whatever was already in x, so the value of the global variable x is now the list.

在第二个示例中,您创建列表推导,但随后将其值分配给(全局)变量x。这会覆盖x中已有的内容,因此全局变量x的值现在是列表。

In both cases, when you call one of the functions in the list (any one!), it returns the current value of x. You can see this here:

在这两种情况下,当您调用列表中的一个函数(任何一个!)时,它将返回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

#2


6  

I guess you are on python 2.x, where in a list comprehension, the temporary variable 'leaks' into the namespace. You can read about why in this blog post from Guido.

我猜你是在python 2.x上,在列表解析中,临时变量'泄漏'进入命名空间。您可以在Guido的这篇博客文章中了解原因。

In Python 2, the list comprehension "leaks" the loop control variable into the surrounding scope ... This was an artifact of the original implementation of list comprehensions; it was one of Python's "dirty little secrets" for years.

在Python 2中,列表推导将循环控制变量“泄漏”到周围的范围内......这是列表推导的原始实现的工件;多年来它一直是Python的“肮脏的小秘密”之一。

This has been fixed in python 3.

这已在python 3中修复。

I'm not sure why you are confusing things with the lambda, here you will see the same behaviour in this simpler case:

我不确定你为什么要把这些东西与lambda混淆,在这个简单的例子中你会看到相同的行为:

>>> x = 'a'
>>> y = [x for x in 'b','c']
>>> x
'c'
>>> x = [x for x in 'b','c']
>>> x
['b', 'c']

#3


2  

>>> x='a'
>>>x = [lambda : x for x in range(3)]

as soon as the iteration starts the x gets assigned to 0, returned from range()(and and reference to 'a' is removed). In the final iteration the value of x becomes 2, and as soon as the LC exits the LC gets assigned to x, so now x points to the LC.

一旦迭代开始,x被赋值为0,从range()返回(并删除对'a'的引用)。在最后的迭代中,x的值变为2,并且一旦LC退出,LC就被分配给x,所以现在x指向LC。

example:

例:

>>> [x for x in range(3)]
[0, 1, 2]
>>> x     
2
>>> x=[x for x in range(3)]
>>> x
[0, 1, 2]