类中生成器的变量范围

时间:2016-11-28 16:09:42

标签: python variables generator

我认为我知道变量和生成器在Python中是如何工作的 但是,以下代码让我感到困惑。

from __future__ import print_function

class A(object):
    x = 4
    gen = (x for _ in range(3))

a = A()
print(list(a.gen))

运行代码(Python 2)时,它说:

Traceback (most recent call last):
  File "Untitled 8.py", line 10, in <module>
    print(list(a.gen))
  File "Untitled 8.py", line 6, in <genexpr>
    gen = (x for _ in range(3))
NameError: global name 'x' is not defined

在Python 3中,它说NameError: name 'x' is not defined
但是,当我跑步时:

from __future__ import print_function

class A(object):
    x = 4
    lst = [x for _ in range(3)]

a = A()
print(a.lst)

代码在Python 3中不起作用,但它在Python 2中或在像这样的函数中起作用

from __future__ import print_function

def func():
    x = 4
    gen = (x for _ in range(3))
    return gen

print(list(func()))

此代码适用于Python 2和Python 3或模块级

from __future__ import print_function

x = 4
gen = (x for _ in range(3))

print(list(gen))

该代码也适用于Python 2和Python 3。

class为何错误?

3 个答案:

答案 0 :(得分:6)

因为x是一个类属性(静态变量),您可以访问它,

示例

>>> class A(object):
...     x = 4
...     gen = (A.x for _ in range(3))
...
>>> a = A()
>>> list(a.gen)
[4, 4, 4]

这里甚至gen是另一个类属性,这意味着,

>>> b = A()
>>> list(b.gen)
[]

这是空的,因为发电机已经耗尽。

<小时/> 发生这种情况是因为只有在您发出a.gen时才会评估生成器,因为它无法解析名称x

答案 1 :(得分:5)

正如其他答案中所述,它发生的是True,因为它是静态变量。但是,限制代码工作的不仅仅是那个属性。实际原因是变量的范围及其执行的范围。例如,创建一个类:

class A(object):
    x = 999999
    y = x +1

如果您访问它的类属性A.xA.y,它将起作用。因为,在初始化y时,x会替换为表达式x+1中的值。由于x的范围属于班级。

然而,在发电机的情况下不会发生这种情况。即在你的例子中:

class A(object):
    x = 4
    gen = (x for _ in range(3))

执行list(a.gen)时,它在类外执行(因为在运行时评估生成器)并检查当前作用域中x的引用。由于x未在该范围内初始化,因此会引发错误。

当您显式初始化x=4时,它可以正常工作,因为现在生成器表达式的值可以使用x

为了使您的生成器表达式工作,如其他人所述,您必须将其定义为:

class A(object):
    x = 4
    gen = (A.x for _ in range(3))
    #      ^ mentioning `A.x` is the value to access

答案 2 :(得分:1)

这是因为x是一个类变量。在python中,必须使用self(例如,从实例方法访问)或类名访问类变量。

class A(object):
    x = 4
    gen = (A.x for _ in range(3))

    def call_me(self):
        print self.x

a = A()
a.call_me()
print list(a.gen)

有关详细讨论,请参阅 Static class variables in PythonWhy is Python class not recognizing static variable