列表推导中定义的变量是不是会泄漏到封闭范围内? [复制]
Posted
技术标签:
【中文标题】列表推导中定义的变量是不是会泄漏到封闭范围内? [复制]【英文标题】:Do variables defined inside list comprehensions leak into the enclosing scope? [duplicate]列表推导中定义的变量是否会泄漏到封闭范围内? [复制] 【发布时间】:2015-07-02 20:20:36 【问题描述】:我找不到任何定义这种行为的地方:
if [x for x in [0, 1, -1] if x > 0]:
val = x
这段代码有多安全?如果列表中的任何元素大于 0,val
是否总是分配给列表中的最后一个元素?
【问题讨论】:
我试过了(在 python 2.6.6 上,但我想差别不大),对我来说结果是 -1。我想这与列表理解的工作方式有关。我认为首先替换值,然后检查 if 子句。 (顺便说一句,我有点惊讶 x 在理解范围之外......) 谢谢,我在问题中打错字了,在循环结束时 val 似乎总是等于 -1 我假设如果返回一个列表,那么 x 将始终保持等于最后一个元素在列表中,或者至少看起来是这样。我也很惊讶 x 仍在范围内。 当我使用上面的代码并向列表中添加更多元素时,@MatthewTodd val 似乎确实等于列表中的最后一个元素。在旁注中,print [x for x in [0, 1, -1] if x>0]
打印 [1]
。也就是说,它在 python 3 中不起作用。
【参考方案1】:
在 Python 2.x 中,定义在列表推导中的变量会泄漏到它们的封闭范围内,所以是的,val
将始终绑定到在列表推导期间绑定到 x
的最后一个值(只要理解是非空的,因此是“真实的”列表)。
但是,在 Python 3.x 中,情况不再如此:
>>> x = 'foo'
>>> if [x for x in [0, 1, -1] if x > 0]:
... val = x
...
>>> val
'foo'
这种行为(几乎没有)记录在案here:
在 Python 2.3 及更高版本中,列表解析将其包含的每个
for
的控制变量“泄漏”到包含范围内。但是,这种行为已被弃用,并且依赖它在 Python 3 中不起作用。
...随着 Python 3.x 中的更改记录在 here:
[...] 请注意,列表推导具有不同的语义:它们更接近于
list()
构造函数内的生成器表达式的语法糖,特别是循环控制变量不再是泄漏到周围的范围内。
看起来 2.x 的行为并不是任何人特别引以为豪的事情,事实上 Guido van Rossum 在blog post 中将其称为“Python 的“肮脏小秘密之一”。
【讨论】:
以上是关于列表推导中定义的变量是不是会泄漏到封闭范围内? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
Python2中的列表推导式存在变量泄漏问题,在Python3中不存在