Python 类中生成器的变量作用域
我想我很了解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
然而,下面的代码让我感到困惑
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
当在处理类
语句体时设置了值ify时,立即查找。(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