函数在使用之前应该定义吗?但为什么以下代码有效:
def main():
dog()
def dog():
print("This is a dog.")
if __name__ == '__main__':
main()
我的意思是 dog() 是在它被调用之后定义的,它是如何工作的?
实际上它不是(在它被调用后定义)。该脚本将执行以下操作:
那时dog
在全球范围内已经知道并且main
可以调用它。
该名称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
函数在尝试调用它时会失败。
函数/方法块中的代码在函数被调用之前不会执行。并且 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
。