Python中的最大recursion深度是多less,以及如何增加?

我有这个尾recursion函数:

def fib(n, sum): if n < 1: return sum else: return fib(n-1, sum+n) c = 998 print(fib(c, 0)) 

它工作到n = 997,然后它只是打破和吐出“比较RuntimeError超过最大recursion深度”。 这只是一个堆栈溢出? 有没有办法避开它?

这是一个防止堆栈溢出,是的。 Python(或更确切地说,CPython实现)不会优化尾recursion,而无约束的recursion会导致堆栈溢出。 您可以使用sys.setrecursionlimit来更改recursion限制,但这样做是危险的 – 标准限制稍微保守,但是Python堆栈框架可能相当大。

Python不是一种function语言,尾recursion不是一个特别有效的技术。 如果可能的话,迭代地重写algorithm通常是更好的主意。

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

 sys.setrecursionlimit(1500) 

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

来自python网站 :

sys.getrecursionlimit()

返回recursion限制的当前值,即Python解释器堆栈的最大深度。 此限制可以防止无限recursion导致C堆栈溢出并导致Python崩溃。 它可以通过setrecursionlimit()来设置。

使用保证尾部呼叫优化的语言。 或者使用迭代。 或者, 装饰者可爱。

我意识到这是一个老问题,但对于那些阅读,我会build议不要使用recursion来解决这个问题 – 列表要快得多,并且完全避免recursion。 我将这个实现为:

 def fibonacci(n): f = [0,1,1] for i in xrange(3,n): f.append(f[i-1] + f[i-2]) return 'The %.0fth fibonacci number is: %.0f' % (n,f[-1]) 

(如果你从0开始计算斐波那契数列,则使用xrange中的n + 1)

我遇到了类似的问题,错误“超过最大recursion深度”。 我发现这个错误是由我用os.walk循环的目录中的一个损坏的文件触发的。 如果您在解决此问题时遇到问题,并且正在处理文件path,请确保将其缩小,因为它可能是损坏的文件。

当然可以通过应用Binet公式来计算O(1)中的斐波那契数:

 from math import floor, sqrt def fib(n): return int(floor(((1+sqrt(5))**n-(1-sqrt(5))**n)/(2**n*sqrt(5))+0.5)) 

当结果不再适合长时,你将需要从numpy的大整数。

使用发电机?

 def fib(): a, b = 0, 1 while True: yield a a, b = b, a + b fibs = fib() #seems to be the only way to get the following line to work is to #assign the infinite generator to a variable f = [fibs.next() for x in xrange(1001)] for num in f: print num 

上面的fib()函数改编自: http : //intermediatepythonista.com/python-generators

还必须使用resource.setrlimit来增加堆栈大小并防止段错误

Linux内核限制了进程的堆栈。

Python将局部variables存储在解释器的堆栈中,因此recursion会占用解释器的堆栈空间。

如果Python解释器试图超出堆栈限制,则Linux内核会对其进行段错误检测。

堆栈限制大小由getrlimitsetrlimit系统调用进行控制。

Python通过resource模块提供对这些系统调用的访问。

 import resource import sys print resource.getrlimit(resource.RLIMIT_STACK) print sys.getrecursionlimit() print # Will segfault without this line. resource.setrlimit(resource.RLIMIT_STACK, [0x10000000, resource.RLIM_INFINITY]) sys.setrecursionlimit(0x100000) def f(i): print i sys.stdout.flush() f(i + 1) f(0) 

当然,如果你不断增加ulimit,你的RAM就会耗尽,这会使你的电脑因为交换的疯狂而停下来,或者通过OOM Killer来杀死Python。

从bash中,您可以看到并设置堆栈限制(kb):

 ulimit -s ulimit -s 10000 

我的默认值是8Mb。

也可以看看:

  • 在python脚本中设置stacksize
  • Python:什么是Linux,Mac和Windows的硬recursion限制?

在Ubuntu 16.10,Python 2.7.12上testing

许多人build议增加recursion限制是一个很好的解决scheme,但不是因为总会有限制。 而是使用迭代解决scheme。

 def fib(n): a,b = 1,1 for i in range(n-1): a,b = b,a+b return a print fib(5) 

正如@alex build议的那样 ,你可以使用一个生成器函数来执行此操作。 下面是你问题中代码的等价物:

 def fib(n): def fibseq(n): """ Iteratively return the first n Fibonacci numbers, starting from 0 """ a, b = 0, 1 for _ in xrange(n): yield a a, b = b, a + b return sum(v for v in fibseq(n)) print format(fib(100000), ',d') # -> no recursion depth error