Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 课程评估的顺序?_Python_Class_Python 3.x_Enums - Fatal编程技术网

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
的顺序是什么