我有下面的一段代码,失败的错误如下:

RuntimeError:超出最大递归深度

我尝试重写这个代码,以允许尾部递归优化(TCO)。我相信,如果进行了TCO,那么该代码应该是成功的。

def trisum(n, csum):
    if n == 0:
        return csum
    else:
        return trisum(n - 1, csum + n)

print(trisum(1000, 0))

我是否应该得出结论,Python不做任何类型的TCO,或者我只是需要以不同的方式定义它?


当前回答

除了优化尾部递归,你还可以手动设置递归深度:

import sys
sys.setrecursionlimit(5500000)
print("recursion limit:%d " % (sys.getrecursionlimit()))

其他回答

不,而且永远不会,因为吉多·范·罗森更喜欢有正确的回溯

尾递归消去(2009-04-22)

尾部呼叫的最后遗言(2009-04-27)

你可以用这样的转换手动消除递归:

>>> def trisum(n, csum):
...     while True:                     # Change recursion to a while loop
...         if n == 0:
...             return csum
...         n, csum = n - 1, csum + n   # Update parameters instead of tail recursion

>>> trisum(1000,0)
500500

基于Guido van Rossum关于该主题的陈述,CPython现在不支持,将来也可能永远不会支持尾部调用优化。

我听说过这样的说法,因为它修改堆栈跟踪的方式,使得调试更加困难。

除了优化尾部递归,你还可以手动设置递归深度:

import sys
sys.setrecursionlimit(5500000)
print("recursion limit:%d " % (sys.getrecursionlimit()))

尝试实验macropy TCO实现的大小。

Python中没有内置的尾部递归优化。但是,我们可以通过抽象语法树(AST)“重建”函数,消除那里的递归,并用循环替换它。Guido是绝对正确的,这种方法有一些局限性,所以我不推荐使用。

然而,我仍然编写了我自己的优化器版本(而不是作为一个训练示例),您甚至可以尝试它是如何工作的。

通过pip安装此包:

pip install astrologic

现在你可以运行这个示例代码:

from astrologic import no_recursion

counter = 0

@no_recursion
def recursion():
    global counter
    counter += 1
    if counter != 10000000:
        return recursion()
    return counter

print(recursion())

这个解决方案不稳定,您永远不应该在生产中使用它。你可以在github的页面上阅读一些重要的限制(俄语,抱歉)。然而,这个解决方案是相当“真实”的,没有中断代码和其他类似的技巧。