Python 2.7 列表解析泄露变量名

Python 2.7 list comprehension leaks variable name

我正在使用列表理解为 Python2.7 中的 class 属性赋值。我注意到这会将列表理解中使用的变量添加为 class 属性。

class MyClass:
    some_strings = [s for s in ('Foo','Bar')]

print MyClass.s

Output: 'Bar' #??

有人可以解释为什么会这样吗?在那里使用列表理解有什么问题吗?

没有错。使用列表理解将其变量添加到本地范围,就像 for 循环一样。当在 class 定义中使用时,所述局部范围用于初始化 class 属性。如果您不想在您的 class.

中使用 del 名称 s
class MyClass:
  some_strings = [s for s in ('Foo','Bar')]
  del s

请注意,在 Python 3(使用 3.4 测试)中,列表理解将 不会 将其变量添加到本地范围。

解释来自Guido Van Rossum

We also made another change in Python 3, to improve equivalence between list comprehensions and generator expressions. In Python 2, the list comprehension "leaks" the loop control variable into the surrounding scope: x = 'before' a = [x for x in 1, 2, 3] print x # this prints '3', not 'before'

This was an artifact of the original implementation of list comprehensions; it was one of Python's "dirty little secrets" for years. It started out as an intentional compromise to make list comprehensions blindingly fast, and while it was not a common pitfall for beginners, it definitely stung people occasionally. For generator expressions we could not do this. Generator expressions are implemented using generators, whose execution requires a separate execution frame. Thus, generator expressions (especially if they iterate over a short sequence) were less efficient than list comprehensions.

However, in Python 3, we decided to fix the "dirty little secret" of list comprehensions by using the same implementation strategy as for generator expressions. Thus, in Python 3, the above example (after modification to use print(x) :-) will print 'before', proving that the 'x' in the list comprehension temporarily shadows but does not override the 'x' in the surrounding scope.