检查以下代码:
>>> def fib(x):
... if x == 0 or x == 1:
... return 1
... else:
... return fib(x-1) + fib(x-2)
>>> print(fib(4))
根据SoloLearn Python教程(针对Recursion)中的注释,代码的工作原理如下:
1. fib(4) = fib(3) + fib(2)
2. = (fib(2) + fib(1)) + (fib(1) + fib(0))
3. = fib(1) + fib(0) + fib(1) + fib(1) + fib(0)
4. = 1+ 1 + 1 + 1 + 1
5. = 5
在第2行之后,只有fib(2)
应该成为fib()
函数的其他部分,对吧?
两个fib(1)
和单个fib(0)
符合fib()
函数的if部分的条件。所以返回1。我的问题是,为什么在第3行,fib(1) + fib(0) + fib(1) + fib(1) + fib(0)
全部被1&替换,然后添加?
请原谅我提出这样一个noob问题。
答案 0 :(得分:4)
这是一个双递归函数,因此它的调用结果是调用的树结构,其基本情况为fib(1)和fib(0)
fib(4) = fib(3) + fib(2)
/ \ / \
fib(4) = ( fib(2) + fib(1) ) + ( fib(1) + fib(0) )
/ \ | | |
fib(4) = ( ( fib(1) + fib(0) ) + fib(1) ) + ( fib(1) + fib(0) )
| | | | |
fib(4) = ( ( 1 + 1 ) + 1 ) + ( 1 + 1 )
\ / | \ /
fib(4) = ( ( 2 ) + 1 ) + ( 2 )
\ / |
fib(4) = ( 3 ) + ( 2 )
\ /
fib(4) = 5
您还可以通过在正确的位置添加一些打印件以及一个额外的辅助参数来显示函数的工作,以帮助它和其他一些小的更改
>>> def fib(n, nivel=0):
if n==0 or n==1:
print(" "*nivel,"fib(",n,")=1")
return 1
else:
print(" "*nivel,"fib(",n,")")
result = fib(n-1,nivel+1) + fib(n-2,nivel+1)
print(" "*nivel,"fib(",n,")=",result)
return result
>>> fib(4)
fib( 4 )
fib( 3 )
fib( 2 )
fib( 1 )=1
fib( 0 )=1
fib( 2 )= 2
fib( 1 )=1
fib( 3 )= 3
fib( 2 )
fib( 1 )=1
fib( 0 )=1
fib( 2 )= 2
fib( 4 )= 5
5
>>>
在这里你可以注意到呼叫从左到右依次解决,并且自下而上
答案 1 :(得分:3)
我认为代码如何工作的描述具有误导性,因为它似乎表明,当从一行到下一行时,不会评估每个值。如果我们通过它调用的函数(或它返回的值)替换下一行的所有内容,并在示例中添加括号,我们得到以下内容,这可能有助于您更好地理解该代码的内部工作原理:
1. fib(4)
2. = fib(3) + fib(2)
3. = (fib(2) + fib(1)) + (fib(1) + fib(0))
4. = ((fib(1) + fib(0)) + 1) + (1 + 1)
5. = 1 + 1 + 1 + 2
6. = 5
答案 2 :(得分:2)
@MorganThrapp是对的。更具体地说,递归函数fib
的基本情况是:
if x==0 or x==1:
return 1
调用fib(1)
或fib(0)
时会触发此子句。在编程用语中,函数将计算为其返回值,此处为1
。
在fib(4)
的示例中,使用fib
或1
输入调用0
五次,并将这些结果全部添加到一起,从而导致您的最终返回值5
,从原来的fib(4)
调用返回并立即传递到print
函数。