递归 - Python,返回值问题
Posted
技术标签:
【中文标题】递归 - Python,返回值问题【英文标题】:Recursion - Python, return value question 【发布时间】:2010-12-08 18:36:09 【问题描述】:我意识到这听起来像是一个愚蠢的问题,但我上次编写它是在汇编程序中,所以我的想法可能是错误的:
这样的递归函数:
def fac(n):
if n == 0:
return 1
else:
return n * fac(n - 1)
为什么当函数到达 n == 0 时它不返回 1 而是返回阶乘的答案。我在想像在汇编程序中那样的东西,当 n == 0 时:
mov eax, 1
ret
为什么上面的代码可以工作,我想python返回那个条件之前堆栈上的最后一个值?
【问题讨论】:
【参考方案1】:这样想,例如fac(5)
:
return 5 * fac(4)
return 4 * fac(3)
return 3 * fac(2)
return 2 * fac(1)
return 1 * fac(0)
1
所以1
将是第一个 返回值,但它会返回到fac(1)
,fac(1)
将返回到fac(2)
等等。
【讨论】:
+1:记住,“函数”的返回值并不是整个表达式的返回值,它涉及到许多乘法和函数调用。这完全是关于“调用堆栈”和评估函数的上下文。 谢谢,这是一个基本的错过。但我认为这是我的错误,这完全有道理,干杯!【参考方案2】:它确实在 n == 0 时返回 1。该返回值从调用站点的堆栈中弹出,这是在 n * fac(n - 1)
处的调用。 1
乘以 n
并返回,等等。
【讨论】:
是的,但是可以说 n == 4,它仍然会迭代并递减一个计数器,直到它到达行尾,在我的逻辑中是当 n == 0 时,即不再剩下的数字要相乘。也许我在这里混淆了一些非常基本的东西,但我没有找到任何关于 Python 如何进行递归的解释。我也可以使用 do while 循环来执行此功能,然后会更清楚。但正如它现在所写的那样,我只是无法遵循逻辑,希望这是有道理的?【参考方案3】:如果您调用 fac(0) 它将返回 1(不是 0,但我想这只是您问题中的一个错字)。如果你调用 fac(1),它将进入 else 子句,并在那里调用fac(0)
。这将返回 1。然后它将计算 n*1,即 1,并将其返回。如果你调用fac(2)
,它也将进入else 子句,在那里它将调用fac(1)
,如上所述将返回1,所以n*fac(n-1)
将是2,这就是fac(2)
的返回值。等等。我希望能为你解释它。
【讨论】:
【参考方案4】:没有隐式返回 - 当 n=0 时,函数进入 if 语句,并直接从 return 1
语句返回 1。
但是,这不是将“阶乘答案”返回给用户的点。相反,它可能会将此值返回给
调用 由 fac(1) 调用的函数,它位于 n * fac(n - 1)
分支的中间。因此它将返回“1”并返回n*1
,它是1 给它的 调用者。如果是 fac(2),它将返回 n * 1
,或 2 给 它的调用者等等。
因此 fac(5) 被翻译为:
fac(5) = 5 * fac(4) = 5 * (4 * fac(3) = 5 * (4* (3 * fac(2)) = 5 * (4* (3 * (2 * fac(1)) = 5 * (4* (3 * (2 * (1 * fac(0)) = 5*4*3*2*1*1
只有在通过每个上层返回 1 值后,它才会返回到第一个调用者,每个阶段的乘法会给你答案。
【讨论】:
【参考方案5】:James,当对您的函数的最终调用(当 n==0 时)返回时,它只是调用堆栈上的几个 fac(n) 实例之一。如果说 print(fac(4)),栈本质上是:
fac(0)
fac(1)
fac(2)
fac(3)
fac(4)
print()
对 fac(0) 的最终调用适当地返回 1,但是在 Python 中,您已经请求了对 fac(n) 的第一次调用的返回值,即 fac(4)。
不要认为它是一个循环,其中 'ret' 会爆发,返回只是结束几个待执行的执行之一。
【讨论】:
以上是关于递归 - Python,返回值问题的主要内容,如果未能解决你的问题,请参考以下文章