递归代码中未触发预期条件的finally块为何仍执行并输出对应打印内容?
递归代码中未触发预期条件的finally块为何仍执行并输出对应打印内容?
嘿,这个问题问得挺有意思的,我来给你拆解一下到底发生了什么~
首先先把你的代码贴出来方便分析:
def divisive_recursion(n): try: if n <= 0: return 1 else: return n + divisive_recursion(n // divisive_recursion(n - 1)) except ZeroDivisionError: return -1 finally: if n == 2: print("Finally block executed for n=2") elif n == 1: print("Finally block executed for n=1") print(divisive_recursion(5))
你疑惑的点在于:明明divisive_recursion(1)陷入了无限递归,为什么finally里n=1和n=2的打印语句都会执行?其实核心原因是Python在处理递归深度溢出的RecursionError时,会回溯整个调用栈,每个栈帧对应的函数的finally块都会被强制执行,不管这个函数有没有正常返回。
具体的调用和执行流程是这样的:
- 当你调用
divisive_recursion(5),它会依次触发divisive_recursion(4)→divisive_recursion(3)→divisive_recursion(2)→divisive_recursion(1)。 - 到
divisive_recursion(1)时,计算n // divisive_recursion(n-1):n-1=0,divisive_recursion(0)返回1,所以1//1=1,于是divisive_recursion(1)会递归调用它自己,进入无限循环。 - 当递归次数超过Python的默认递归深度限制时,会抛出
RecursionError。这时候Python会从最底层的栈帧开始,逐层向上清理调用栈,每清理一个栈帧,就会执行对应函数里的finally块。
这时候关键的点来了:
- 栈里存在一个
divisive_recursion(2)的帧(就是从divisive_recursion(3)调用过来的那个),当回溯到这个帧时,n的值是2,所以finally里的n==2条件成立,就会打印Finally block executed for n=2。 - 栈里还有大量
divisive_recursion(1)的帧(无限递归产生的),每回溯到一个这样的帧,n的值都是1,所以finally里的n==1条件成立,就会打印Finally block executed for n=1(你可能会看到这个打印多次,因为栈里有很多这样的帧)。
你之前误以为“n永远不会等于1或2”,但实际上divisive_recursion(2)和divisive_recursion(1)都被实实在在地调用过,只是因为无限递归没正常返回,但异常回溯时,这些函数的finally块都会被触发执行,自然就会打印出对应的内容啦。
备注:内容来源于stack exchange,提问作者Puna
相关产品推荐
相关产品推荐

