Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 类中生成器的变量作用域_Python_Variables_Generator - Fatal编程技术网

Python 类中生成器的变量作用域

Python 类中生成器的变量作用域,python,variables,generator,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)时,会显示: 该代码在Python3中不起作用,但在Python2或类似的函数中起作用 from __future__ import p

我想我很了解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)时,会显示:

该代码在Python3中不起作用,但在Python2或类似的函数中起作用

from __future__ import print_function

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

print(list(func()))
此代码在Python2和Python3中或在模块级别上运行良好

from __future__ import print_function

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

print(list(gen))
该代码在Python2和Python3中也运行良好


为什么在
class
中它是错误的?

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

示例

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

这里甚至还有另一个class属性
gen
,这意味着

>>> b = A()
>>> list(b.gen)
[]
由于发电机已耗尽,因此将提供空的



之所以会出现这种情况,是因为只有当您发出
a.gen
时,生成器才能对其求值,因为
x
是一个类变量,因此它无法解析名称
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)
有关详细讨论,请参阅 和

如其他答案中所述,之所以出现这种情况是因为它是静态变量。但限制代码工作的不仅仅是该属性。实际原因是变量的范围及其执行的范围。例如,创建一个类:

class A(object):
    x = 999999
    y = x +1
如果访问它的类属性
A.x
A.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

我以为
x
是一个类变量而不是一个静态变量?我错了吗?这不完全是
True
。将
gen
替换为
y=x+1
。然后像
a.y
一样访问它。它会工作的。为什么它不能与
gen
一起工作?@moinuddinkadri与
y=x+1
一起工作,
x
当在处理
语句体时设置了值if
y时,立即查找。
(x表示范围(3)内的uu))
创建一个生成器表达式,在您实际尝试使用结果生成器中的值之前,不会对其主体进行求值。也就是说,
x
的查找发生在
class
语句之外。@MoinuddinQuadri很好,但生成器会在稍后的时间点求值。@nu11p01n73R为什么
lst=[x for uu in range(3)]
在Python 3中引发错误语句
在类外执行(因为生成器在运行时被评估),检查当前范围内x**的引用**
可能会引起争议。请看,结果是[6,6,6],而不是[5,5,5],为什么?
class A(object):
    x = 4
    gen = (x for _ in range(3))
class A(object):
    x = 4
    gen = (A.x for _ in range(3))
    #      ^ mentioning `A.x` is the value to access