试图掌握递归函数

时间:2015-01-23 08:47:14

标签: python function python-2.7 recursion

我试图掌握递归的概念,我无法理解它。 有人可以向我解释它为什么会这样运作吗?

当我看到这段代码时,我希望打印的唯一内容是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的连接!这更可能是因为我的经验受到限制,而不是社区解释我的问题的能力。希望所提供的信息能够在我回到这一点以及其他人时帮助我。谢谢!我会放弃投票,但没有这样做的声誉,对不起!

4 个答案:

答案 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使用Fibn=1进行调用,在这种情况下n=2将返回1.它会向其调用者返回1,这是实例使用Fib调用Fib函数时的函数。所以,当您使用n=3致电Fib时会发生什么:

3不是1或2,所以控制再次转到n=3Fib的最后一行。这一次,这一行调用return Fib(n-1) + Fib(n-2) Fib上的n-1n-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了解。