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

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,或者我只是需要以不同的方式定义它?


当前回答

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

其他回答

Guido的话在http://neopythonic.blogspot.co.uk/2009/04/tail-recursion-elimination.html

I recently posted an entry in my Python History blog on the origins of Python's functional features. A side remark about not supporting tail recursion elimination (TRE) immediately sparked several comments about what a pity it is that Python doesn't do this, including links to recent blog entries by others trying to "prove" that TRE can be added to Python easily. So let me defend my position (which is that I don't want TRE in the language). If you want a short answer, it's simply unpythonic. Here's the long answer:

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的页面上阅读一些重要的限制(俄语,抱歉)。然而,这个解决方案是相当“真实”的,没有中断代码和其他类似的技巧。

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

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

尾递归消去(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现在不支持,将来也可能永远不会支持尾部调用优化。

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