列表推导中定义的变量会泄漏到封闭范围内吗?

Do variables defined inside list comprehensions leak into the enclosing scope?

我找不到定义此行为的任何地方:

if [x for x in [0, 1, -1] if x > 0]:
    val = x

这段代码安全吗?如果列表中的任何元素大于 0,是否总是将 val 分配给列表中的最后一个元素?

在 Python 2.x 中,列表推导中定义的变量会泄漏到它们的封闭范围内,所以是的,val 将始终绑定到绑定到 [=12= 的最后一个值] 在列表理解期间(只要理解的结果是非空的,因此 "truthy",列表)。

然而,在Python 3.x中,情况已不再如此:

>>> x = 'foo'
>>> if [x for x in [0, 1, -1] if x > 0]:
...     val = x
... 
>>> val
'foo'

该行为(几乎没有)被记录 here:

In Python 2.3 and later releases, a list comprehension “leaks” the control variables of each for it contains into the containing scope. However, this behavior is deprecated, and relying on it will not work in Python 3.

...随着 Python 3.x 中的更改记录 here:

[...] note that list comprehensions have different semantics: they are closer to syntactic sugar for a generator expression inside a list() constructor, and in particular the loop control variables are no longer leaked into the surrounding scope.

看来 2.x 的行为并不是任何人都特别引以为豪的事情,事实上 Guido van Rossum 将其称为“Python 之一”"dirty little secrets"' 在 blog post.