Python 列表理解重写值

问题描述 投票:0回答:4

看看下面的代码,它显示了列表理解:

>>> i = 6
>>> s = [i * i for i in range(100)]
>>> print(i)

当您在 Python 2.6 中执行代码示例时,它会打印 99,但是当您在 Python 3.x 中执行它时,它会打印 6。

改变行为的原因是什么?为什么 Python 3.x 中的输出是 6?

python list-comprehension
4个回答
33
投票

旧的行为是一个错误,但无法轻易修复,因为某些代码依赖于它。

列表理解中的变量

i
应该与顶层的变量
i
不同。从逻辑上讲,它应该有自己的范围,不会扩展到理解之外,因为它的值只有在理解内部才有意义。但在 Python 2.x 中,由于实现细节,作用域大于必要的范围,导致变量“泄漏”到外部作用域,导致您看到令人困惑的结果。

Python 3.0 故意不向后兼容以前的版本,因此他们利用这个机会修复了这种不良行为。

在Python 2.3及更高版本中,列表理解将其包含的每个控制变量“泄漏”到包含范围中。然而,这种行为已被弃用,并且依赖它在 Python 3.0 中将不起作用

来源


7
投票

是的,这是有原因的,原因是他们不希望列表理解中的临时变量泄漏到外部命名空间中。因此,这是一个有意的更改,是列表推导式现在成为将生成器表达式传递给 list() 的语法糖的结果。

参考:PEP3100


5
投票

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

(当然,在 Python 3 中,这是固定的,列表推导式不再泄漏控制变量)


0
投票

对我来说,范围似乎发生了变化。

我在Python 2.6中确认了你的结果;它确实打印了 99,这是列表理解中分配给 i 的最后一个值。

© www.soinside.com 2019 - 2024. All rights reserved.