应该在使用之前定义函数吗?但为什么以下代码有效:
def main():
dog()
def dog():
print("This is a dog.")
if __name__ == '__main__':
main()
我的意思是dog()是在调用之后定义的,它是如何工作的?
答案 0 :(得分:7)
实际上它不是(在被称之后定义)。该脚本将执行以下操作:
此时dog
已在全球范围内公开,main
可以调用它。
答案 1 :(得分: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
函数在尝试调用时失败。
答案 2 :(得分:2)
在调用函数之前,函数/方法块中的代码不会执行。 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
内的所有代码都被立即执行,并且在执行的那一刻,命名空间/范围无法访问名称Dog
。