在递归函数中,我们需要在函数体中显式返回函数吗?

时间:2018-04-07 13:21:14

标签: python recursion return greatest-common-divisor

我被指示使用Euclid方法找到gcd。我最初在Python中写了以下内容:

def gcdRecur(a,b):
    if b==0:
        print('I am here')
        return a
    else:
        gcdRecur(b,a%b)
        print(a,b)

print(gcdRecur(51,187))

结果是:

I am here
34 17
51 34
187 51
51 187
None

我不知道为什么它的输出是这样的,然后我意识到要查看其他代码,一个是明确地使用return语句。

def gcdRecur(a,b):
    if b==0:
        print('I am here')
        return a
    else:
        return gcdRecur(b,a%b)
        print(a,b)


print(gcdRecur(51,187))

我得到了

I am here
17

所以我得到了我想要的东西并且知道我们应该使用return语句而不是只调用函数。

我的问题是为什么第一个代码的输出被反转了?为什么即使没有使用return语句,以下代码也能正常工作

def tower(n,fr,to,spare):
    if n==1:
        print_move(fr,to)
    else:
        tower(n-1,fr,spare,to)
        tower(1,fr,to,spare)
        tower(n-1,spare,to,fr)

以上代码是我在麻省理工学院EDX课程中学到的,它解决了河内塔问题。

这里的代码运行正常。因此,当我想以相反的顺序执行时,我们直接调用递归函数并按正确的顺序使用return语句,我是对的吗?

2 个答案:

答案 0 :(得分:0)

  

我的问题是为什么第一个代码的输出会反转?

严格意义上并没有真正逆转,但我想我明白你的意思。你或许期望"父母"在"孩子之前打电话打印"调用

如果我们检查代码,我们会看到:

def gcdRecur(a,b):
    if b==0:
        print('I am here')
        return a
    else:
        gcdRecur(b,a%b)  # make child call
        print(a,b)       # print from the parent call

如果您将两者交换掉,它会打印出您可能称之为"正确的方式":

def gcdRecur(a,b):
    if b==0:
        print('I am here')
        return a
    else:
        # swap printing and recursive calls
        print(a,b)       # print from the parent call
        gcdRecur(b,a%b)  # make child call

但是,如果您使用return语句,则该函数会在到达return时终止,因此如果我们在之后打印 return声明到达,打印永远不会发生。如果我们需要,我们可以使用try - finally构造。

更深入,如果我们" 追踪"一个程序,例如(这是不是有效的Python代码,更多的是让我们深入了解这些调用的处理方式):

gcdRecur(51,187)
    if 187 == 0:  # fails
    else:  # we take the else branch
        gcdRecur(187,51)
            if 51 == 0:  # fails
            else:  # we take the else branch
                gcdRecur(51,34)
                    if 51 == 0:  # fails
                    else:  # we take the else branch
                        gcdRecur(34,17)
                            if 51 == 0:  # fails
                            else:  # we take the else branch
                                gcdRecur(17,0)
                                    if 0 == 0:  # succeeds!
P                                       print('I am here')
                                        return 17
P                               print(34,17)
P                       print(51,34)
P               print(187,51)
P       print(51,187)

我在这里标记了print左侧带有P的行。如您所见,P的行的顺序相同。

答案 1 :(得分:-1)

当然你应该退回电话。

你正在做一个返回一些东西的方法。在你的“别人”中,你什么都不返回。