我一直在尝试理解以下代码,它是我的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
中没有元素。但是,如果它再次召唤自己,那不就意味着它再也没有回报吗?这让我非常困惑。
答案 0 :(得分:2)
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。
答案 1 :(得分:1)
就像它开始倒退一样。
那是因为它确实如此,这是一个尾递归的例子,它没有在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))))
最上层的递归必须在上述级别之前完成评估,因此只有在列表耗尽后才会实际开始将数字加在一起,然后启动将持续递归调用。 (列表的末尾)
但是,如果它再次召唤自己,那是不是意味着它又不会返回任何东西?
是的,但只有在它可以返回一些东西而不需要另一个递归调用之后,它可以返回一些东西,然后上面的级别可以返回,然后上面的级别......
答案 2 :(得分: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。
答案 3 :(得分:0)
考虑以下代码:
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的长度以及如何处理一个层。
答案 4 :(得分: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