这里有一个尾递归函数

def recursive_function(n, sum):
    if n < 1:
        return sum
    else:
        return recursive_function(n-1, sum+n)

c = 998
print(recursive_function(c, 0))

它一直工作到n=997,然后它就中断并抛出一个RecursionError:在比较中超过了最大递归深度。这只是一个堆栈溢出吗?有办法绕过它吗?


当前回答

如果你经常需要改变递归限制(例如在解决编程难题时),你可以定义一个简单的上下文管理器,像这样:

import sys

class recursionlimit:
    def __init__(self, limit):
        self.limit = limit

    def __enter__(self):
        self.old_limit = sys.getrecursionlimit()
        sys.setrecursionlimit(self.limit)

    def __exit__(self, type, value, tb):
        sys.setrecursionlimit(self.old_limit)

然后调用具有自定义限制的函数,您可以这样做:

with recursionlimit(1500):
    print(fib(1000, 0))

从with语句体退出时,递归限制将恢复到默认值。

附注:您可能还想增加Python进程的堆栈大小,以获得较大的递归限制值。例如,这可以通过ulimit shell内置或limits.conf(5)文件来完成。

其他回答

import sys
sys.setrecursionlimit(1500)

def fib(n, sum):
    if n < 1:
        return sum
    else:
        return fib(n-1, sum+n)

c = 998
print(fib(c, 0))

看起来你只需要设置一个更高的递归深度:

import sys
sys.setrecursionlimit(1500)

我不确定我是不是在重复某人的意思但前段时间有人写了一个y算子用于递归调用函数

def tail_recursive(func):
  y_operator = (lambda f: (lambda y: y(y))(lambda x: f(lambda *args: lambda: x(x)(*args))))(func)
  def wrap_func_tail(*args):
    out = y_operator(*args)
    while callable(out): out = out()
    return out
  return wrap_func_tail

然后递归函数需要形式:

def my_recursive_func(g):
  def wrapped(some_arg, acc):
    if <condition>: return acc
    return g(some_arg, acc)
  return wrapped

# and finally you call it in code

(tail_recursive(my_recursive_func))(some_arg, acc)

对于斐波那契数,你的函数是这样的:

def fib(g):
  def wrapped(n_1, n_2, n):
    if n == 0: return n_1
    return g(n_2, n_1 + n_2, n-1)
  return wrapped

print((tail_recursive(fib))(0, 1, 1000000))

输出:

..684684301719893411568996526838242546875

(实际上是数字的音调)

如果你只想得到很少的斐波那契数,你可以使用矩阵法。

from numpy import matrix

def fib(n):
    return (matrix('0 1; 1 1', dtype='object') ** n).item(1)

它的速度很快,因为numpy使用了快速求幂算法。结果是O(log n)比比奈公式好因为它只使用整数。但如果你想让所有的斐波那契数都不超过n,最好是死记硬背。

这是为了避免堆栈溢出。Python解释器限制了递归的深度,以帮助您避免无限递归,从而导致堆栈溢出。 尝试增加递归限制(sys.setrecursionlimit)或重写不使用递归的代码。

来自Python文档:

sys.getrecursionlimit () 返回递归限制的当前值,即Python解释器堆栈的最大深度。这个限制可以防止无限递归导致C堆栈溢出和Python崩溃。可以通过setrecursionlimit()来设置。