1

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

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

print MyClass.s

Output: 'Bar' #??

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

4

2 回答 2

2

没有任何错误。使用列表推导将其变量添加到本地范围,就像for循环一样。当在类定义中使用时,所述局部范围用于初始化类属性。如果您不想在课堂上使用del该名称,则必须使用该名称。s

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

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

于 2016-07-01T14:52:05.990 回答
1

Guido Van Rossum的解释

我们还在 Python 3 中进行了另一项更改,以改进列表推导和生成器表达式之间的等价性。在 Python 2 中,列表推导将循环控制变量“泄漏”到周围的作用域中: x = 'before' a = [x for x in 1, 2, 3] print x # this prints '3', not 'before'

这是列表推导的原始实现的产物;多年来,它一直是 Python 的“肮脏小秘密”之一。它最初是为了让列表理解速度极快而故意妥协,虽然这对初学者来说不是一个常见的陷阱,但它确实偶尔会刺痛人们。对于生成器表达式,我们不能这样做。生成器表达式是使用生成器实现的,其执行需要单独的执行框架。因此,生成器表达式(特别是如果它们在短序列上迭代时)不如列表推导效率高。

然而,在 Python 3 中,我们决定通过使用与生成器表达式相同的实现策略来修复列表推导的“肮脏小秘密”。因此,在 Python 3 中,上面的示例(修改为使用 print(x) :-) 将打印 'before',证明列表推导中的 'x' 暂时隐藏但不会覆盖周围的 'x'范围。

于 2016-07-01T15:12:33.093 回答