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 列表理解泄漏变量名 [重复]的主要内容,如果未能解决你的问题,请参考以下文章
我的元组中的那些小“u”是啥? (python 2.7)[重复]