1

函数在使用之前应该定义吗?但为什么以下代码有效:

def main():
    dog()

def dog():
    print("This is a dog.")

if __name__ == '__main__':
    main()

我的意思是 dog() 是在它被调用之后定义的,它是如何工作的?

4

3 回答 3

7

实际上它不是(在它被调用后定义)。该脚本将执行以下操作:

  • 创建函数并将其分配给“main”
  • 创建函数并将其分配给“狗”
  • 叫“主”

那时dog在全球范围内已经知道并且main可以调用它。

于 2013-09-13T20:42:02.717 回答
6

该名称dog被查找为全局名称。在实际使用之前,对全局变量的引用不需要引用任何已定义的内容。该函数在被调用之前main()不会使用。dog

如果dog未定义,调用main()将导致NameError异常:

>>> def main():
...     return dog()
... 
>>> main()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in main
NameError: global name 'dog' is not defined
>>> def dog():
...     return 'Woof!'
... 
>>> main()
'Woof!'

Python 并不真正关心什么dog . 我也可以使它成为一个类,或者甚至是不可调用的东西:

>>> class dog:
...     pass
... 
>>> main()
<__main__.dog instance at 0x10f7d3488>
>>> dog = 'Some string'
>>> main()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in main
TypeError: 'str' object is not callable

因为在最后一个示例中,dog现在绑定到一个字符串,所以该main函数在尝试调用它时会失败。

于 2013-09-13T20:41:28.383 回答
3

函数/方法块中的代码在函数被调用之前不会执行。并且 CPython 语言实现(这是最常见的,也是您可能正在使用的)不会像 C 等语言那样在编译时进行名称检查。由于它主要是一种解释性语言,它会检查名称是否在在运行时动态命名空间。

此外,您应该了解的有关 Python 的一点是,类中的代码是在类创建时执行的,但方法/函数中的代码不是。一条def语句只是将函数的名称添加到命名空间。在调用函数之前,它不会在函数本身内运行任何代码。

考虑以下合法的 Python 代码。

class Something:
    def __init__(self):
        self.puppy = Dog()

class Dog:
    def __init__(self):
        pass

inst = Something()

这是完全合法的,因为在定义类__init__之前不会运行。Dog但是,如果我们将构造函数移到 Dog 类的创建之上呢?

此代码会抱怨 NameError 因为 Dog 尚未定义!

class Something:
    def __init__(self):
        self.puppy = Dog()

inst = Something()

class Dog:
    def __init__(self):
        pass

最后一个例子……

此代码会抱怨相同的 NameError。

class Something:
    my_puppy = Dog()
    def __init__(self):
        self.puppy = Dog()

class Dog:
    def __init__(self):
        pass

inst = Something()

这是因为里面的所有代码Something都会立即执行,并且在执行的那一点上,命名空间/范围没有访问 name 的权限Dog

于 2013-09-13T21:00:32.793 回答