课程评估顺序?

时间:2014-06-16 19:47:07

标签: 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 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中对枚举的引用出错。由于没有错误,并且似乎运行正常,我想知道在同一模块中以及不同模块之间引用类的(排序)规则是什么?为什么没有错误?

3 个答案:

答案 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)

理解代码中评估顺序的最简单方法是观察它的执行:

http://dbgr.cc/q

按下调试按钮最右侧的播放按钮,它将自动单步执行。

我认为令您感到困惑的是,在定义class E时,E类内的所有语句都会运行。每个类定义都是这种情况。这包括调用print函数说出"In Enum",以及定义v1类的v2E成员。

c.meth(E.v1)C类都已定义之前,行E尚未执行,这意味着E.v1也已定义。这就是为什么没有像你期望的那样的错误。