Python 课程评估的顺序?
在一个文件Python 课程评估的顺序?,python,class,python-3.x,enums,Python,Class,Python 3.x,Enums,在一个文件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 enu
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)
运行时,我得到以下输出:
枚举中的
C.meth().v1中的
现在,由于Python是一种解释语言(至少在使用IDLE时是这样),我希望在方法meth
中引用枚举时会出现错误。由于没有错误,而且运行正常,我想知道在同一个模块中以及在不同模块之间引用类的(排序)规则是什么?为什么没有错误?导入模块时,命令从上到下执行。在类
-定义中,也会执行命令,以定义类内的方法。def
定义了一个方法,但是不执行def
中的命令,而只解析这些命令。导入模块时,这些命令从上到下执行。在类
-定义中,也会执行命令,以定义类内的方法。def
定义了一个方法,但是def
中的命令不会执行,而只会被解析。名称查找在运行时发生。因此,当您定义类C
及其方法meth
时,还没有完成对E
的查找。因此,事后定义它并不是一个问题。相反,在调用该方法时会进行查找
此外,名称查找是通过向上查找范围来进行的,因此meth
将查找在模块级别声明的原始E
,而不管您是否将其导入main.py
。由于您还在main.py
中导入E
,这是对同一对象的引用,因此您也可以在其中引用相同的枚举值
另请参见此示例:
>>> 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
(即使尚未初始化),foo
将始终*解析为本地foo
(nonlocal
语句允许将foo
设置为非本地,对于该方法中的foo
的所有使用,再次将其解析为外部范围。)名称查找在运行时进行。因此,当您定义类C
及其方法meth
时,还没有完成对E
的查找。因此,事后定义它并不是一个问题。相反,在调用该方法时会进行查找
此外,名称查找是通过向上查找范围来进行的,因此meth
将查找在模块级别声明的原始E
,而不管您是否将其导入main.py
。由于您还在main.py
中导入E
,这是对同一对象的引用,因此您也可以在其中引用相同的枚举值
另请参见此示例:
>>> 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
(即使尚未初始化),foo
将始终*解析为本地foo
(nonlocal
语句允许将foo
设置为非本地,在该方法中使用foo
时,再次将其解析到外部范围。)理解代码中求值顺序的最简单方法是观察它的执行:
按下调试按钮最右侧的播放按钮,它将自动单步执行
我认为让您感到困惑的是,当定义classe
时,E
类中的所有语句都会运行。每个类定义都是这样。这包括调用print函数在Enum中显示,,以及定义E
类的v1
和v2
成员
直到定义了c
和E
类,才执行c.meth(E.v1)
行,这意味着也已经定义了E.v1
。这就是为什么没有出现预期的错误。理解代码中求值顺序的最简单方法是观察代码的执行:
按下调试按钮最右侧的播放按钮,它将自动单步执行
我认为让您感到困惑的是,当定义classe
时,E
类中的所有语句都会运行。每个类定义都是这样。这包括调用print函数在Enum中显示,,以及定义E
类的v1
和v2
成员
直到定义了c
和E
类,才执行c.meth(E.v1)
行,这意味着也已经定义了E.v1
。这就是为什么没有出现您预期的错误。好的,那么解释器如何知道E.v1
的顺序是什么