为什么Python打印这个全局变量而不是类属性?

为什么Python打印这个全局变量而不是类属性?,python,Python,我试图理解Python代码何时会引用模块级变量而不是类级变量。我在模块中有以下代码,main.py' ## main.py # global variable x x = "I am global and I love it!" class SomeClass: x = "I am a class attribute, and life is good!" print(x) # prints "I am a class attribute, and life is good

我试图理解Python代码何时会引用模块级变量而不是类级变量。我在模块中有以下代码,
main.py
'

## main.py

# global variable x
x = "I am global and I love it!"

class SomeClass:
    x = "I am a class attribute, and life is good!"
    print(x)  # prints "I am a class attribute, and life is good!"
    def __init__(self):
        print(x)  # prints "I am global and I love it!"  Why?

print(x)  # prints "I am global and I love it!"
SomeClass()
导入此模块时,输出为:

I am a class attribute, and life is good!
I am global and I love it!
I am global and I love it!
为什么在
SomeClass.\uuuu init\uuuu
方法中打印全局变量,而在类主体中打印类属性
x

这是根据Python邮件列表上的一个问题解释的:

导入模块 无论何时导入模块,Python都会按照模块编写的顺序执行所有模块级代码。它将所有定义的名称附加到模块对象,模块的导入器可以通过模块对象访问所有定义的名称。这样您就可以导入模块,并且模块中的名称不会破坏您的命名空间

import main  # executes the script main.py, then creates a module
print(main.x)
定义类 您可以认为Python创建类的方式与创建模块的方式类似:它执行类主体中的所有代码,然后将定义的名称分配给类。
\uuuu init\uuuu
方法也成为类的一个属性调用函数时,类已被构造,在函数中,您只能将
x
类属性引用为
SomeClass.x
(或
self.x
内部的
\uuu init\uuu
)。类定义的命名空间与模块的命名空间不同,因此类中的
print(x)
首先查找类命名空间,因为
print
位于同一命名空间中

import main  # executes the script main.py, then creates a module
print(main.x)
在一边 正如在中时不能引用当前模块一样,也不能引用当前类。例如:

class SomeOtherClass:
    x = 5
    SomeOtherClass.x = 6  # This fails!
无法引用该类的原因与无法从模块中引用所处模块的原因相同:名称尚未创建


这个答案的灵感来自于。Python中的类定义创建了一个名称空间,但并不创建新的作用域。这意味着类内定义的函数不能直接访问包含类的变量。相反,它们必须作为类或实例的属性访问它们

因此,您可以通过使用
SomeClass.x
self.x
来获取类变量,而不是在示例的
\uuuuu init\uuuu
函数中访问
x

print(x)
在类主体中工作的原因是该代码以类名称空间作为其本地名称空间运行。但是,如果您试图在类级别执行更复杂的操作,您可能会遇到许多问题,因为无作用域命名空间是一个相当奇怪的环境。例如,这将不起作用:

class Foo:
    x = 1
    dct = {i: x for i in range(10)}

您将得到一个关于
x
变量的
namererror
,因为字典理解在它自己的作用域中运行,并且看不到类变量
x
,它是在无作用域的类名称空间中定义的。

我喜欢dict理解不起作用的示例。
import main  # executes the script main.py, then creates a module
print(main.x)