我试图掌握递归的概念,我无法理解它。 有人可以向我解释它为什么会这样运作吗?
当我看到这段代码时,我希望打印的唯一内容是1,因为它最终会退出调用自身,这就是它在最后一次调用时返回的内容。
def Fib(n):
if n == 1 or n == 2:
return 1
return Fib(n-1) + Fib(n-2)
print Fib(10)
我也尝试这样做,并期望它打印1,但只能得到无
def foo(n):
if n == 1:
return n
else:
foo(n-1)
print foo(10)
编辑:我感谢提供的帮助。我仍然没有看到我的大脑需要AH-HA的连接!这更可能是因为我的经验受到限制,而不是社区解释我的问题的能力。希望所提供的信息能够在我回到这一点以及其他人时帮助我。谢谢!我会放弃投票,但没有这样做的声誉,对不起!
答案 0 :(得分:1)
class noisyOne():
def __init__(self, val=1):
self.val = val
def __add__(self, other):
print("**Adding {0} with {1}**".format(self.val, other.val))
return noisyOne(self.val + other.val)
def __str__(self):
return str(self.val)
def Fib(n, side):
if n == 1 or n == 2:
print ("return 1 : called from {0}".format(side))
return noisyOne(1)
print("return Fib({0}) + Fib({1}) : called from {2}".format(n-1, n-2, side))
return Fib(n-1, 'Fib({0})'.format(n-1)) + Fib(n-2, 'Fib({0})'.format(n-2))
print (Fib(5, 'Fib(5)'))
# return Fib(4) + Fib(3) : called from Fib(5) : Fib(5) = Fib(4) + Fib(3)
# return Fib(3) + Fib(2) : called from Fib(4) : Fib(4) = Fib(3) + Fib(2) -> Fib(5) = Fib(3) + Fib(2) + Fib(3)
# return Fib(2) + Fib(1) : called from Fib(3) : Fib(3) = Fib(2) + Fib(1) -> Fib(5) = Fib(2) + Fib(1) + Fib(2) + Fib(3)
# return 1 : called from Fib(2) : Fib(2) = 1 -> Fib(5) = 1 + Fib(1) + Fib(2) + Fib(3)
# return 1 : called from Fib(1) : Fib(1) = 1 -> Fib(5) = 1 + 1 + Fib(2) + Fib(3)
# **Adding 1 with 1** : 1 + 1 = 2 -> Fib(5) = 2 + Fib(2) + Fib(3)
# return 1 : called from Fib(2) : Fib(2) = 1 -> Fib(5) = 2 + 1 + Fib(3)
# **Adding 2 with 1** : 2 + 1 = 3 -> Fib(5) = 3 + Fib(3)
# return Fib(2) + Fib(1) : called from Fib(3) : Fib(3) = Fib(2) + Fib(1) -> Fib(5) = 3 + Fib(2) + Fib(1)
# return 1 : called from Fib(2) : Fib(2) = 1 -> Fib(5) = 3 + 1 + Fib(1)
# return 1 : called from Fib(1) : Fib(1) = 1 -> Fib(5) = 3 + 1 + 1
# **Adding 1 with 1** : 1 + 1 = 2 -> Fib(5) = 3 + 2
# **Adding 3 with 2** : 3 + 2 = 5 -> Fib(5) = 5
# 5
答案 1 :(得分:1)
代码不会打印1,因为函数返回1的唯一方法是参数n
为1或2.所以当你说print Fib(10)
时,结果将是不是1。
相反,控件转到if
语句(return Fib(n-1) + Fib(n-2)
)之后的下一行,它再次调用Fib
,这次是9和8.这两个函数的结果电话会被加在一起并返回。
所以现在Fib
运行时参数n
设置为9.由于9不等于1或2,Fib
函数的最后一行将再次运行,{{对于值8和7,将再次调用1}}。
此操作会继续,直到Fib
使用Fib
或n=1
进行调用,在这种情况下n=2
将返回1.它会向其调用者返回1,这是实例使用Fib
调用Fib
函数时的函数。所以,当您使用n=3
致电Fib
时会发生什么:
3不是1或2,所以控制再次转到n=3
,Fib
的最后一行。这一次,这一行调用return Fib(n-1) + Fib(n-2)
Fib
上的n-1
和n-2
,即1.这两个函数调用都计算为1,因此函数返回1 + 1到它的来电者。
然后,调用者将其添加值返回给调用者,调用者将其添加值返回给调用者,直到调用者为print
行,然后打印结果。
答案 2 :(得分:1)
我认为你缺少的关键是方法调用会创建一个堆栈。所以想想调用的顺序。
第一个调用是参数10
。所以这是我们的调用堆栈:
__main__
Fib(10)
我们当前的子程序(方法)位于底部。
然后Fib(10)
使用参数9
调用子例程,因此我们的调用堆栈如下所示:
__main__
Fib(10)
Fib(9)
一直到Fib(2)
:
__main__
Fib(10)
Fib(9)
Fib(8)
Fib(7)
Fib(6)
Fib(5)
Fib(4)
Fib(3)
Fib(2)
此时,Fib(2)
进入if
区块,我们点击return 1
。现在关键是:return
只有从堆栈中弹出一个元素。因此,当Fib(2)
返回时,我们会返回到Fib(3)
:
__main__
Fib(10)
Fib(9)
Fib(8)
Fib(7)
Fib(6)
Fib(5)
Fib(4)
Fib(3)
现在计算总和中的第一项,Fib(3)
可以移动到总和中的第二项。这使它调用Fib(1)
:
__main__
Fib(10)
Fib(9)
Fib(8)
Fib(7)
Fib(6)
Fib(5)
Fib(4)
Fib(3)
Fib(1)
也会立即返回:
__main__
Fib(10)
Fib(9)
Fib(8)
Fib(7)
Fib(6)
Fib(5)
Fib(4)
Fib(3)
Fib(1)
返回后,Fib(3)
最终会返回:
__main__
Fib(10)
Fib(9)
Fib(8)
Fib(7)
Fib(6)
Fib(5)
Fib(4)
然后Fib(4)
拨打Fib(2)
,就像Fib(3)
之前调用Fib(1)
一样:
__main__
Fib(10)
Fib(9)
Fib(8)
Fib(7)
Fib(6)
Fib(5)
Fib(4)
Fib(2)
依此类推。如果最终return
令您感到困惑,请记住return
只会结束当前子例程并将您重新投入上一个子例程。
关于你提出的第二种方法,你得到None
,因为它应该是return foo(n-1)
,而不仅仅是foo(n-1)
。
答案 3 :(得分:0)
你忘了返回foo(n-1)的值,它不是递归函数,默认情况下会返回None。试试这个:
def foo(n):
if n == 1:
return 1
else:
return foo(n-1)
print foo(10)
当您调用该函数时,无论该函数是多少,它都将永远返回1。
首先,如果n == 1则返回1,否则如果n = 5,则返回foo(4),foo(4)返回foo(3),foo(3)返回foo(2),foo( 1)返回1.因此,如果你打印foo(100)或foo(200),它将永远是1。
请记住,n必须是正数,否则你会得到这个:
RuntimeError: maximum recursion depth exceeded
打印出来的过程:
def Fib(n):
print "Call number", n
if n == 1 or n == 2:
return 1
print '\n now is', Fib(n-1) + Fib(n-2)
return Fib(n-1) + Fib(n-2)
print Fib(10)
可以帮助PO了解。