繁体   English   中英

试图理解Python中的递归

[英]Trying to understand recursion in Python

我一直试图理解下面的代码,这是我的Python书中的一个递归示例:

def mysum(L):
    if not L:
        return 0
    else:
        return L[0] + mysum(L[1:])


print(mysum([1, 2, 3, 4, 5]))

output: 15

我很难理解它是如何工作的,以及它是如何返回的15

我试图将代码重写为:

def mysum(L):
    if not L:
        return 0
    else:
        temp = L[0] + mysum(L[1:])
        print(temp)
        return temp


mysum([1, 2, 3, 4, 5])

这个输出:

5
9
12
14
15

但我仍然不确定这是如何工作的,就像它开始倒退一样。 5 + 4 + 3 + 2 + 1

return L[0] + mysum(L[1:])
我知道右边的函数在函数返回任何内容之前执行。 在这种情况下,它是递归的,它会调用自身,直到L中没有元素。 但如果它再次召唤自己,那是不是意味着它又不会返回任何东西? 这对我来说非常困惑。

L[0]是列表的头部, L[1:]是其余部分。 在每次调用中,函数都会添加第一个元素和剩余列表的总和。

所以发生的事情是:

mysum([1, 2, 3, 4, 5]) => 1 + mysum([2, 3, 4, 5])
mysum([1, 2, 3, 4, 5]) => 2 + mysum([3, 4, 5])
mysum([1, 2, 3, 4, 5]) => 3 + mysum([4, 5])
mysum([1, 2, 3, 4, 5]) => 4 + mysum([5])
mysum([1, 2, 3, 4, 5]) => 5 + mysum([])
mysum([]) => 0

在最后一次通话之后,一切都会回来

也许你不仅可以打印你的温度,还可以打印L.

就像它开始倒退一样。

好吧那是因为它有点,这是一个尾递归的例子,没有在python中优化,想象用括号中的结果替换mysum(L[1:]) ,你会得到这样的东西:

#L[0] + mysum(L[1:])
mysum([1,2,3,4,5])
1 + mysum([2,3,4,5])
1 + (2 + mysum([3,4,5]))
1 + (2 + (3 + mysum([4,5])))
1 + (2 + (3 + (4 + mysum([5]))))
1 + (2 + (3 + (4 + (5 + mysum([])))))
1 + (2 + (3 + (4 + (5 + 0))))

内部最高级别的递归必须在上述级别之前完成评估,因此只有在列表耗尽后才开始将数字加在一起,然后启动将持续递归调用。 (列表的末尾)

但如果它再次召唤自己,那是不是意味着它又不会返回任何东西?

是的,但只有它可以返回一些东西而不需要另一个递归调用,然后它可以返回一些东西,然后上面的级别可以返回,然后上面的级别...

让我们按照您的第一部分代码,我们将其称为列表[1,2,3,4,5]

第一个调用有L = [1,2,3,4,5]所以进入第二部分并执行:

return 1 + mysum([2,3,4,5])

再次调用mysum,现在使用较小的列表,其中:

return 2 + mysum([3,4,5])

接下来:

return 3 + mysum([4,5])

然后:

return 4 + mysum([5])

再一次正常流程:

return 5 + mysum([])

这次我们传递的列表是空的,我们的函数返回0.这个级联返回堆栈,这意味着mysum([5])现在的计算结果为5(5 + 0 = 5),这导致了对mysum的评估([4] ,5))etcetera一直到我们的第一次调用返回15。

考虑以下代码:

def mysum0(L):
    return 0

def mysum1(L):
    return L[0] + mysum0(L[1:])

def mysum2(L):
    return L[0] + mysum1(L[1:])

def mysum3(L):
    return L[0] + mysum2(L[1:])

def mysum4(L):
    return L[0] + mysum3(L[1:])

print(mysum4([1, 2, 3, 4]))

每个函数mysum[n]总结一个长度为n的列表,并委托给mysum[n-1]来帮助它。 你能理解它是如何工作的吗? 递归的mysum函数就像所有mysum[n]函数合二为一。 它只需要知道如何处理列表0的长度以及如何处理一个层。

您可以测试您提出的假设问题:当递归到达列表中只有一个元素时会发生什么?

>>>print(mysum([5]))

收益:

5

因为它执行:

return L[0] + mysum(L[1:])

L [0]返回5,并且mysum(L [1:])(因为L [1:]不存在,长度为1的列表)返回0。

所以,既然函数已经完成了,它可以计算递归中的下一个神秘,对于L = [4,5],它变成:

return L[0] + mysum[L[1:]

这相当于:

return 4 + mysum[5]

因为我们计算的mysum [5] = 5,相当于:

return 4 + 5

暂无
暂无

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

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