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

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

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

print MyClass.s

Output: 'Bar' #??

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

【问题讨论】:

    标签: python-2.7 list-comprehension class-attributes


    【解决方案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'范围。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-03
      • 2018-04-04
      • 2015-11-28
      • 2016-06-11
      • 2011-06-15
      • 2014-05-06
      • 2015-11-28
      • 1970-01-01
      相关资源
      最近更新 更多