【问题标题】:Scope of class variable with list comprehension [duplicate]具有列表理解的类变量的范围[重复]
【发布时间】:2014-05-12 22:18:16
【问题描述】:

看看下面这段代码:

class a:
    s = 'python'
    b = ['p', 'y']
    c = [x for x in s]

输出:

>>> a.c
['p', 'y', 't', 'h', 'o', 'n']

但是当我尝试使用 if 限制列表时:

class a:
    s = 'python'
    b = ['p', 'y']
    c = [x for x in s if x in b]

显示以下异常:

Traceback (most recent call last):
  File "<pyshell#22>", line 1, in <module>
    class a:
  File "<pyshell#22>", line 4, in a
    c = [x for x in s if x in b]
  File "<pyshell#22>", line 4, in <listcomp>
    c = [x for x in s if x in b]
NameError: global name 'b' is not defined

如果 make global b 有效,为什么会这样?

【问题讨论】:

    标签: python scope list-comprehension


    【解决方案1】:

    这与其说是关于列表推导中的变量范围,不如说是关于类的工作方式。在 Python 3 (but not in Python 2!) 中,列表推导不会影响它们周围的范围:

    >>> [i for i in range(10)]
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> i
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'i' is not defined
    >>> i = 0
    >>> [i for i in range(10)]
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> i
    0
    

    但是,当您在类中执行此操作时,它不会像在模块或函数的本地范围内那样在类属性中查找b。要执行您想要执行的操作,请使用 @property 装饰器:

    >>> class a:
    ...   s = 'python'
    ...   b = 'py'
    ...   @property
    ...   def c(self):
    ...     return [x for x in self.s if x in self.b]
    ... 
    >>> A = a()
    >>> A.c
    ['p', 'y']
    

    此外,请记住字符串也是可迭代的(它们只是其组成字符的列表),因此无需显式地将 b 设为列表。

    【讨论】:

    • 谢谢!! b 是上面的列表,因为它没有精确的字符串:D 再次感谢!!!
    • @grkiran2011(新用户)提出以下问题:抱歉,无法理解所提供的解释。我的意思是列表理解如何看到字符串 s,而不是列表 b。能否请您澄清一下。
    • @kvantour 上下文略有不同:在它“缩放”特定元素的部分中,它看不到封闭范围内的内容(这里是 if ... 部分)。但是,它确实会看到那些将列表理解提供给容器以供使用的外部变量。
    猜你喜欢
    • 1970-01-01
    • 2013-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-19
    • 2019-07-14
    • 2012-08-21
    相关资源
    最近更新 更多