请看下面的一段代码,它展示了一个列表推导式。
>>> i = 6
>>> s = [i * i for i in range(100)]
>>> print(i)
在Python 2.6中执行该代码示例会打印99,但在Python 3.x中执行时会打印6。
为什么更改了行为,并且在Python 3.x中输出为6?
提前感谢您的回答!
请看下面的一段代码,它展示了一个列表推导式。
>>> i = 6
>>> s = [i * i for i in range(100)]
>>> print(i)
在Python 2.6中执行该代码示例会打印99,但在Python 3.x中执行时会打印6。
为什么更改了行为,并且在Python 3.x中输出为6?
提前感谢您的回答!
旧的行为是一个错误,但是由于某些代码依赖它而不能轻易修复。
列表推导式中的变量i
应该与顶层的i
不同。从逻辑上讲,它应该具有自己的作用域,超出推导式范围而不会扩展到外面,因为它的值只在推导式中有意义。但在Python 2.x中,由于实现细节,作用域比必要的范围更大,导致变量“泄漏”到外部作用域,从而产生您看到的混乱结果。
Python 3.0故意不保持向后兼容以修复此不良行为。
在 Python 2.3 及后续版本中,列表推导式“泄漏”包含在其中的每个 for 的控制变量到包含范围中。然而,这种行为已被弃用,并且依赖它将无法在 Python 3.0 中工作。
Mark Byers回答得非常好。
顺便提一下..
在Python 2.x中,如果你将括号改为圆括号(创建一个生成器表达式而不是列表推导式),你会发现控制变量并没有泄漏。
>>> i = 6
>>> s = (i for i in range(100))
>>> print i
6
对比。
>>> i = 6
>>> s = [i for i in range(100)]
>>> print i
99
s
现在也不包含列表,所以要获得期望的最终结果,必须执行list(s)
。 - Keith看起来对我来说是作用域的变化。
我在Python 2.6中确认了您的结果;它确实打印99,这是列表推导式中分配给i的最后一个值。