看看下面的代码,它显示了列表理解:
>>> 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及更高版本中,列表理解将其包含的每个控制变量“泄漏”到包含范围中。然而,这种行为已被弃用,并且依赖它在 Python 3.0 中将不起作用
是的,这是有原因的,原因是他们不希望列表理解中的临时变量泄漏到外部命名空间中。因此,这是一个有意的更改,是列表推导式现在成为将生成器表达式传递给 list() 的语法糖的结果。
参考:PEP3100。
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 中,这是固定的,列表推导式不再泄漏控制变量)
对我来说,范围似乎发生了变化。
我在Python 2.6中确认了你的结果;它确实打印了 99,这是列表理解中分配给 i 的最后一个值。