[英]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.