Python 2.7 列表理解泄漏变量名 [重复]

Posted

技术标签:

【中文标题】Python 2.7 列表理解泄漏变量名 [重复]【英文标题】:Python 2.7 list comprehension leaks variable name [duplicate] 【发布时间】:2016-11-04 00:51:06 【问题描述】:

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

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

print MyClass.s

Output: 'Bar' #??

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

【问题讨论】:

【参考方案1】:

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

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

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

【讨论】:

我不知道。我正在将一些 Python3 代码翻译成 Python2,我遇到了一个奇怪的错误,这是由于列表理解中的变量覆盖了一个属性。 Python3 的行为绝对是一个明智的改进!我很惊讶我从未在 Python2 的常见问题中看到这一点...... @JacquesGaudin 当我遇到相反的效果时,我真的很惊讶 - 当我预期它没有被覆盖时。有点 hacky... 我同意 Py3 中的行为感觉更干净,通常鼓励更好的代码。【参考方案2】:

来自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'范围。

【讨论】:

以上是关于Python 2.7 列表理解泄漏变量名 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何使用python 2.7通过变量写入文本文件[重复]

python

我的元组中的那些小“u”是啥? (python 2.7)[重复]

理解Python函数和方法

Python2中的列表推导式存在变量泄漏问题,在Python3中不存在

理解python变量赋值[重复]