2016-04-26 75 views
2

我想了解這段代碼爲什麼這種遞歸方式是什麼意思?

def listSum(ls): 
    if not ls: 
     return 0 

    return ls[0] + listSum(ls[1:]) 

兩件事情來煩我有點

  1. if not ls: - 這是什麼意思?沒有具體說明什麼,它在尋找什麼?
  2. ls[0] + listSum(ls[1:]) - 我試過只使用listSum(ls[0:]),我有運行錯誤。爲什麼?我爲什麼要堅持ls[0] + listSum(ls[1:])
+0

1.見https://docs.python.org/3/library/stdtypes.html#真值檢驗,它是*「如果ls'爲空」*的成語。 2.如果你將整個列表('ls [0:]'或只是'ls [:]')傳遞給遞歸調用,它將如何變空? – jonrsharpe

+0

謝謝@jonrsharpe。我應該關閉我的問題嗎? –

+0

空容器是'假'。 –

回答

4

想象一下,這就是所謂的...

listSum([3, 5, 3, 7]) 

它弄下來......

return ls[0] + listSum(ls[1:]) 

...這被評價爲...

return 3 + listSum([5, 3, 7]) 

然後listSum([5, 3, 7])作爲5 + listsum([3, 7])

然後listSum([3, 7])作爲3 + listsum([7])

Then listSum([7]) as 7 + listsum([]),這是not ls踢入並返回0

因此,完整的東西然後評估爲...

3 + 5 + 3 + 7 + 0 

注:

  • listSum(ls[1:])每次縮短列表 - 減少了剩餘的問題的複雜性,直到listSum調用接收空列表:平凡情況if not ls: return 0處理

  • 遞歸解決方案通常由兩部分組成:一個解決方案爲最簡單的可能輸入(或有時,幾個非常簡單的情況),以及一些說如何採取一個ar ls[0:]回報 - bitrarily複雜的輸入,將其降低到一個公式製作是每個至少一點點簡單的一個或多個recusive電話,始終朝着這一簡單可行的輸入

  • 移動「我一直在使用listSum(ls[0:])試圖」的ls副本 - 它會要求相同的列表要處理循環往復

  • 這可以說是更直觀明確地處理一個元素的列表 - if len(ls) == 1: return ls[0] - 但是如果叫任何人listSum([])你想嘗試訪問[0] (在if下面的其他代碼中)並提出一個例外上;處理空列表使得函數更容易使用如果listSum([])返回0對你的應用程序是理智的,但另一方面有listSum([])引發異常可能會發現列表意外空的錯誤 - 你可以決定哪些對你更有用;高高興興如果你這樣做處理空單的情況下,len(ls) == 1話,那麼「只是工程」具有相同的遞歸的邏輯

+0

Hi @ tony-d,比方說我很笨,我想繼續攜帶'listSum(ls [0] :)',我會怎麼樣阻止我這樣做? –

+1

@AndyK系統遞歸限制?同樣,如果你沒有縮短每個遞歸調用的列表,你永遠不會達到空列表的終止條件。 – jonrsharpe

+1

Hi @AndyK - 遞歸調用確實需要一些方法來知道何時停止,否則當jonrsharpe提到堆棧耗盡時,它們會掛起程序或崩潰。 –