关于功能:python如何实现相互递归?

How does python implement mutual recursion?

转到使用C / Java背景的python,我最近不得不实现相互递归,但python中的某些东西困扰着我:

因为python程序是逐行解释的,如果我在同一个python文件中一个接一个地有两个函数:

1
2
3
4
5
6
7
8
def A(n):
    B(n-1)
# if I add A(1) here, it gives me an error
def B(n):
    if n <= 0:
        return
    else:
        A(n-1)

当解释器正在读取A时,尚未定义B,但是此代码不会给我一个错误

TL; DR
我的理解是,当解释def时,python会向{"function name": function address}的某个本地名称空间locals()添加一个条目,
但至于函数体,它只进行语法检查:

1
2
3
4
5
6
def A():
    blabla # this will give an error

def B():
    print x # even though x is not defined, this does not give an error
    A()     # same as above, NameError is only detected during runtime


将在编译时捕获SyntaxError,但大多数其他错误(NameErrorValueError等)将仅在运行时捕获,然后仅在调用该函数时捕获。

"如果我已经编写了一个函数,如果它没有在我的测试中调用.." - 这就是为什么你应该测试一切。

有些IDE会在各种情况下发出警告,但最好的选择仍然是自己进行彻底的测试。这样,您还可以检查由用户输入等因素引起的错误,IDE的自动检查不会涵盖这些错误。


B(n-1)表示"执行此语句时,在模块范围中查找某个函数B,然后使用参数n-1调用它"。由于在执行函数时发生了查找,因此可以在以后定义B

(此外,您可以使用不同的函数完全覆盖B,然后A将调用新的B。但这可能会导致一些令人困惑的代码。)

如果您担心不能捕获对不存在的函数的调用,可以尝试使用静态分析工具。除此之外,请确保您正在测试您的代码。


When the interpreter is reading A, B is not yet defined, however this code does not give me an error

python解释器没有给出错误的原因可以在docs中找到,在技术上称为前向引用:

Name resolution of free variables occurs at runtime, not at compile time.