簡體   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