在文件lib.py
中,我定义了一个功能类C
和一个枚举类E
,如下所示:
class C:
a = None
def meth(self, v):
if v == E.v1:
print("In C.meth().v1")
a = E.v1
if v == E.v2:
print("In C.meth().v2")
a = E.v2
from enum import Enum
class E(Enum):
print("In Enum")
v1 = 1
v2 = 2
然后,我将这两个类导入我的模块main.py
并使用枚举:
from lib import C
from lib import E
c = C()
c.meth(E.v1)
运行时,我得到以下输出:
In Enum
In C.meth().v1
现在,由于Python是一种解释型语言(至少在使用IDLE时),我希望在方法meth
中对枚举的引用出错。由于没有错误,并且似乎运行正常,我想知道在同一模块中以及不同模块之间引用类的(排序)规则是什么?为什么没有错误?
答案 0 :(得分:2)
名称查找在运行时发生。因此,当您定义类C
及其方法meth
时,E
上的查找尚未完成。因此,之后定义它不是问题。相反,当您调用方法时会发生查找。
此外,通过提升范围进行名称查找,因此meth
会在模块级别找到原始的E
,无论您是否在main.py
中导入它。由于您还在E
中导入了main.py
,这是对相同对象的引用,因此您也可以在其中引用相同的枚举值。
另见这个例子:
>>> def test(): # foo is not defined at this time
print(foo)
>>> test()
NameError: global name 'foo' is not defined
>>> foo = 'bar' # after defining foo, it works:
>>> test()
bar
在定义方法时,变量永远不会“嵌入”;方法只包含名称,并在运行时查找这些名称。但是,由于Python进行查找的方式,局部变量的名称总是“围绕”,即使它们尚未初始化。这可能导致UnboundLocalError
s:
>>> def test():
print(foo)
foo = 'baz'
>>> test()
UnboundLocalError: local variable 'foo' referenced before assignment
有人可能会在第一次打印的外部范围中查找foo
,但因为有一个本地foo
(即使它尚未初始化),{{1永远*将解析为本地foo
。
(* foo
语句允许nonlocal
非本地,将其解析到外部范围 - 再次所有使用foo
方法。)
答案 1 :(得分:1)
导入模块时,命令从上到下执行。在class
- 定义内部,还执行命令,以定义类中的方法。 def
定义了一个方法,但def
中的命令不会被执行,只会被解析。
答案 2 :(得分:1)
理解代码中评估顺序的最简单方法是观察它的执行:
按下调试按钮最右侧的播放按钮,它将自动单步执行。
我认为令您感到困惑的是,在定义class E
时,E
类内的所有语句都会运行。每个类定义都是这种情况。这包括调用print函数说出"In Enum"
,以及定义v1
类的v2
和E
成员。
在c.meth(E.v1)
和C
类都已定义之前,行E
尚未执行,这意味着E.v1
也已定义。这就是为什么没有像你期望的那样的错误。