在模块中定义之前使用的属性

时间:2012-02-20 13:17:28

标签: python class module method-resolution-order

以下是代码:

#a.py
ALL_FUNC = [bar, foo]  #a list containing all the functions defined in this module

def bar():
    pass

def foo():
    pass

然后,我这样运行: $ python a.py NameError:名称'bar'未定义

错误表示bar执行时未定义ALL_FUNC = [bar, foo]。但为什么解释器不能在模块中找到函数bar?只是因为在bar之后定义ALL_FUNC

看看这个,这是一个python类,

class A:
    def __init__(self):
        self.bar()

    def bar(self):
        pass

a = A()

显然,上面的代码会在没有任何错误的情况下运行,但bar中的A也会在访问它之后定义(在__init__中),为什么self.bar()可以发现没有任何错误?

跟进

这是另一个模块,

#b.py
def bar():
    print k  #well, apparently this line will result in an error
def foo():
    pass

if __name__ == '__main__':
    foo()

然后像这样运行,

$ python b.py

没有错误!为什么? bar应该会导致错误,不是吗?仅仅因为__main__没有使用它,所以没有检测到错误?但bar的定义是执行的,对吧?

2 个答案:

答案 0 :(得分:2)

解释器从上到下执行脚本。

def是一个可执行语句。在执行相关def语句之前,foo创建的任何名称(例如第一个示例中的bardef)都不存在。

现在转到第二个示例:当self.bar() 被称为时,名称__init__()被解析,而整个类定义之后被称为被人看见了。

答案 1 :(得分:2)

但是为什么解释器不能在模块中找到功能栏?只是因为bar是在ALL_FUNC之后定义的?

因为代码按照它在文件中出现的顺序执行。在尝试将值分配给ALL_FUNC时,函数定义尚未执行。

但A中的栏也是在访问它之后定义的(在__init__中),为什么可以找到self.bar()而没有任何错误?

因为在定义了类之后调用了__init__。在类定义之后,您的类由a = A()实例化。


对跟进的回应

为什么? bar应该会导致错误,不是吗?仅仅因为__main__没有使用它,所以没有检测到错误?但是bar的定义是执行的,对吗?

如果您致电bar(),则会获得NameError。定义bar函数时,函数代码解释,而不是执行。我不确定除了SyntaxError s之外是否还会提取其他内容,但绝对不是NameError s。

但是,bar并不总是会导致错误。考虑:

>>> def bar():
...   print(k)
...
>>> bar()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in bar
NameError: global name 'k' is not defined
>>> k = "Foo"
>>> bar()
Foo