Python递归RuntimeError

时间:2014-04-09 19:39:44

标签: python recursion

def f1():
    f1()

我们都知道在Python中调用这个函数会产生RuntimeError: maximum recursion depth exceeded

我写了一个简洁的修改版本:

def f2():
    try:
        f2()  #This line throws an error
    finally: #except works too
        f2()  #This line does not throw an error!

第二个函数永远运行而不会抛出RuntimeError。更重要的是,我无法通过 Ctrl C 组合来阻止它。

我不明白为什么调用f2()不会抛出RuntimeError。你能解释一下吗?

2 个答案:

答案 0 :(得分:4)

异常仍然被抛出,但是在Python之前可以显示它你再次调用f2()

所以每次提出异常时,你都会潜入另一个电话。允许那个递归调用(因为我们比限制低一步),我们越过限制,再次引发异常,finally处理程序在另一个调用中偷偷摸摸,几乎是无限的。

由于同样的原因,

CTRL-C并未结束该计划;引发异常(KeyboardInterrupt),但finally:处理程序再次将您送回递归。

你现在正以这样的速度下降,你进入了解释器的轨道。

所有结束,但finally处理程序在堆栈完全展开之前添加指数增长的额外调用数量:

>>> import sys
>>> def f2(depth=0, final=0):
...     try:
...         print depth
...         f2(depth + 1, final)
...     finally:
...         print 'finally:', final
...         f2(depth, final + 1)
... 
>>> sys.setrecursionlimit(5)
>>> f2()
0
1
2
3
finally: 0
finally: 0
2
finally: 1
finally: 0
1
2
finally: 1
finally: 1
1
finally: 2
finally: 0
0
1
2
finally: 1
finally: 1
1
finally: 2
finally: 1
0
1
finally: 2
finally: 2
0
finally: 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in f2
  File "<stdin>", line 7, in f2
  File "<stdin>", line 7, in f2
  File "<stdin>", line 7, in f2
RuntimeError: maximum recursion depth exceeded

答案 1 :(得分:4)

当堆栈填满时,它会在f2内调用try,直到达到最大递归深度。

一旦达到,就会引发RuntimeError,由finally

处理

反过来提升相同的RuntimeError,但现在提升到早期的堆栈,它会传递给finally

在那里,它再次超过最大深度。

当提出KeyboardInterrupt时,程序会一直移动到finally,并且不会退出。

它不会在技术上永远运行,因为只有finally。也就是说,(感谢评论),它允许指数级更多的调用,这非常接近无穷大。递归深度为100将变为2 100 == 1267650600228229401496703205376。

如果每次通话花费1毫秒,则需要 4650亿年才能完成。这只是100的深度