【问题标题】:attributes used before defined in a module在模块中定义之前使用的属性
【发布时间】:2012-02-20 13:17:28
【问题描述】:

代码如下:

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

def bar():
    pass

def foo():
    pass

然后,我这样运行它: $蟒蛇a.py NameError: name 'bar' 没有定义

错误的意思是,bar在执行ALL_FUNC = [bar, foo]时没有定义。但是为什么解释器在模块中找不到函数bar呢?就因为bar是在ALL_FUNC之后定义的?

看这个,这是一个python类,

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

    def bar(self):
        pass

a = A()

显然,上面的代码会运行没有任何错误,但是A中的bar也是在它被访问的位置之后定义的(在__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的定义被执行了对吧?

【问题讨论】:

    标签: python class module method-resolution-order


    【解决方案1】:

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

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

    现在来看您的第二个示例:当__init__()调用时解析名称self.bar(),并且在看到整个类定义之后调用它。 /p>

    【讨论】:

    • 那么,当我运行python a.py时,a.py中的代码会按顺序逐行解释吗?函数使用与否?
    • @Alcott:没错。此外,相同的名称可以在脚本的不同点引用不同的函数。
    • 好吧,我一定很困惑,在C++的模板类中,只有那些使用过的函数会被实例化并生成它们的代码,但是在python的模块中,所有的代码行都会被解释和执行,对吗?
    • @Alcott:差不多。在 Python 中,一切都是动态的,classdef 等实际上都是可执行语句。
    • @Alcott Python 中没有模板,甚至远程也没有。是的,所有代码都已执行,但请注意,在此上下文中,函数声明仅在评估默认参数并创建函数对象时才“执行”,仅此而已。但一般来说,是的。
    【解决方案2】:

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

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

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

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


    回应跟进

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

    如果你打电话给bar(),你会得到一个NameError。当您定义 bar 函数时,函数代码是解释,而不是执行。我不确定这是否会收到除SyntaxErrors 以外的任何内容,但绝对不会收到NameErrors。

    但是,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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-13
      • 1970-01-01
      • 2021-11-05
      • 1970-01-01
      • 2014-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多