在面向对象编程中,为什么Python要为每个递归函数调用创建一个新框架?我试图在互联网上寻找答案,但找不到任何具体的原因或理由。我
发布于 2020-06-27 15:24:51
在某些情况下,Python完全可以重用堆栈帧进行递归函数调用:
def factorial(n, a=1):
if n == 0:
return a
else:
return factorial(n - 1, n * a)
但通常每个调用都需要自己的堆栈框架,因为每个迭代都有一些唯一的状态。假设我们不是立即返回值,而是将它们打印出来:
def factorial2(n, depth=0):
if n == 0:
value = 1
else:
value = n * factorial2(n-1, depth+1)
print(f"Depth: {depth}, Value: {value}")
return value
如果我们调用factorial2(3)
,那么当我们在最深的函数调用时,在不同的堆栈框架中有四个不同的depth
和value
变量。Python稍后需要使用这些值,因此它不能在此期间丢弃堆栈帧。
像Scheme这样的语言在一般情况下仍然会为递归函数创建新的堆栈框架,但在特殊的尾部调用递归情况下,它们可以避免这种情况。在第一个factorial
中,递归是函数返回之前发生的最后一件事,所以像Scheme这样的语言应该知道它可以重用堆栈帧。
Python可以实现这种优化,但Guido van Rossum反对它,认为这会使调试变得更加困难,并鼓励非Python代码。你可以阅读这些博客文章,了解他的完整思考过程:
https://stackoverflow.com/questions/62597492
复制相似问题