简体   繁体   English

递归 - Python,返回值问题

[英]Recursion - Python, return value question

I realize that this may sound like a silly question, but the last time I programmed it was in assembler so my thinking may be off: 我意识到这可能听起来像一个愚蠢的问题,但我最后一次编程它是在汇编程序,所以我的想法可能是关闭的:

A recursive function as so: 递归函数如下:

def fac(n):
    if n == 0:
        return 1
    else:
        return n * fac(n - 1)

Why is it that when the function reaches n == 0 that it does not return 1 but rather the answer which is the factorial. 为什么当函数达到n == 0时它不返回1而是返回因子。 I am thinking something like in assembler it would be when n == 0: 我在思考类似于汇编程序的东西,当n == 0时:

mov eax, 1
ret

Why does the code above work, I suppose python returns the last value on the stack before that condition ? 为什么上面的代码工作,我想python在那个条件之前返回堆栈的最后一个值?

Think about like this, for fac(5) for example: 想想这样,对于fac(5)例如:

return 5 * fac(4)
           return 4 * fac(3)
                      return 3 * fac(2)
                                 return 2 * fac(1)
                                            return 1 * fac(0)
                                                       1

So 1 will be the first returned value but it will be returned to fac(1) and fac(1) will be returned to fac(2) and so on. 因此1将是第一个返回值,但它将返回到fac(1)fac(1)将返回到fac(2) ,依此类推。

It does return 1 when n == 0. That return value is popped off the stack from the calling site, which was the invocation at n * fac(n - 1) . 返回1,当n == 0,即返回值被弹出从调用站点,这是在所述调用栈n * fac(n - 1) That 1 is multiplied by n and returned, etc. 1乘以n并返回等。

If you call fac(0) it will return 1 (not 0, but I suppose that's just a typo in your question). 如果你调用fac(0)它将返回1(不是0,但我想这只是你问题中的一个错字)。 If you call fac(1), it will go in the else clause, and there it will call fac(0) . 如果你调用fac(1),它将进入else子句,并在那里调用fac(0) This will return 1. It will then calculate n*1, which is 1, and return that. 这将返回1.然后它将计算n * 1,即1,然后返回。 If you call fac(2) it will also go in the else clause, where it will call fac(1) which as mentioned above will return 1, so n*fac(n-1) will be 2 and that's the return value of fac(2) . 如果你调用fac(2)它也会进入else子句,它将调用fac(1) ,如上所述将返回1,所以n*fac(n-1)将为2,这是返回值fac(2) And so on. 等等。 I hope that explained it for you. 我希望能为你解释一下。

Nothing's being implicitely returned - when n=0, the function is entering the if statement, and returning 1 directly from the return 1 statement. 没有任何东西被隐含地返回 - 当n = 0时,函数进入if语句,并直接从return 1语句return 1 However, this isn't the point at which the "answer which is the factorial" is returned to the user. 然而,这不是将“作为因子的答案”返回给用户的点。 Instead, it may be returning this value to the calling function invoked by fac(1), which in the middle of the n * fac(n - 1) branch. 相反,它可能会将此值返回到由fac(1)调用的调用函数,该调用函数位于n * fac(n - 1)分支的中间。 Thus it will take the "1" returned and return n*1 , which is 1 to it's caller. 因此,将采取“1”返回,返回n*1 ,也就是1到它的调用者。 If that's fac(2), it'll return n * 1 , or 2 to it's caller and so on. 如果那是fac(2),它将返回n * 1或2给它的调用者,依此类推。

Thus fac(5) gets translated like: 因此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

Only after the 1 value gets returned through each upper layer does it get back to the first caller, and the multiplication at each stage gives you the answer. 只有在通过每个上层返回1值之后,它才会返回到第一个调用者,并且每个阶段的乘法都会给出答案。

James, when the final call to your function (when n==0) returns it's just one of several instances of fac(n) on the call stack. James,当你对函数的最后调用(当n == 0)时,它只是调用堆栈中fac(n)的几个实例之一。 If you say print(fac(4)), the stack is essentially: 如果你说print(fac(4)),那么堆栈本质上是:

fac(0)
fac(1)
fac(2)
fac(3)
fac(4)
print()

The final call to fac(0) appropriately returns 1, however in Python you've requested the return value of the first call to fac(n), fac(4). 对fac(0)的最终调用适当地返回1,但是在Python中你已经请求了第一次调用fac(n),fac(4)的返回值。

Don't think of it as a loop wherein 'ret' will break out, the return simply concludes one of several pending executions. 不要认为它是一个循环,其中'ret'会爆发,返回简单地结束几个待处理的执行之一。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM