Wei*_*gTu 11 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))
Run Code Online (Sandbox Code Playgroud)
运行代码(Python 2)时,它说:
Run Code Online (Sandbox Code Playgroud)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)
Run Code Online (Sandbox Code Playgroud)
该代码在Python 3中不起作用,但它在Python 2中或在像这样的函数中起作用
from __future__ import print_function
def func():
    x = 4
    gen = (x for _ in range(3))
    return gen
print(list(func()))
Run Code Online (Sandbox Code Playgroud)
此代码适用于Python 2和Python 3或模块级别
from __future__ import print_function
x = 4
gen = (x for _ in range(3))
print(list(gen))
Run Code Online (Sandbox Code Playgroud)
该代码也适用于Python 2和Python 3.
为什么错了class?
因为x是一个类属性(静态变量),你可以访问,
例
>>> class A(object):
...     x = 4
...     gen = (A.x for _ in range(3))
...
>>> a = A()
>>> list(a.gen)
[4, 4, 4]
Run Code Online (Sandbox Code Playgroud)
这里甚至gen是另一个类属性,这意味着,
>>> b = A()
>>> list(b.gen)
[]
Run Code Online (Sandbox Code Playgroud)
这是空的,因为发电机已经耗尽.
a.gen时才会评估生成器,而无法解析名称x.
        正如其他答案所述,True它发生的原因是它是静态变量.但是,限制代码工作的不仅仅是那个属性.实际原因是变量的范围及其执行的范围.例如,创建一个类:
class A(object):
    x = 999999
    y = x +1
Run Code Online (Sandbox Code Playgroud)
如果你访问它的类属性A.x和A.y,它会工作.因为,在初始化时y,x将替换表达式中的值x+1.由于范围x是在班级内.
然而,在发电机的情况下不会发生这种情况.即在你的例子中:
class A(object):
    x = 4
    gen = (x for _ in range(3))
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)