2017-07-17 76 views
0

作爲一個練習,我試圖做一個腳本,它會給我一個列表中的項目的總和,但不使用SUM或FOR/WHILE循環。Python:遞歸併返回

我結束了與解決它:

​​3210

這種運作良好,並返回「10」,但我最初的做法是:

def addition(data, total=0): 
    if data != []: 
     total += data.pop() 
     addition(data, total) 
    return total 

print(addition([1,2,3,1,2,1])) 

和代碼返回「1」,第二個位而不是'10'。我無法弄清楚爲什麼這兩種方法沒有做同樣的事情,或者即使第二個例子在數據= []和總數= 10時進入最後一個循環時出現'1',我猜測我錯過了關於變量作用域如何工作的一些規則?

(如下面的答案解釋,它有無關變量的作用域,所以我改變了標題,以反映的問題,任何人在將來對這個事情)

+1

這不是真的與你的問題有關(這在下面得到了很好的回答),但是我想補充一點,Python不會爲尾遞歸提供任何好處,所以你可以簡化你的函數, '如果data:return data.pop()+ addition(data)'用'else:return 0'作爲基本情況。你根本不需要'total'參數,因爲實際的加法是和返回值一起發生的。 – Blckknght

+0

嘿@Blckknght,仍然有點新,我想我正在用錯誤的方式來看遞歸,但看着你的例子,我想我現在明白了。我更像是一個while循環,其中每個迭代都將被線性處理,並且一個循環的輸出將成爲下一個輸入,直到達到基本情況才能打破循環,但在遞歸中情況並非如此,是嗎?這更像是解開其中的同一表達式,直到達到已知的基本情況,然後從最內層的表達式向外解決所有問題。謝謝你,這有助於 –

+0

@Blckknght '高清謊(數據): 如果數據> 1: 回報FIB(數據-1)+ FIB(數據-2) ELIF數據== 1: 回報1 其他: return 0 print(fib(15))' 是的,有了這個想法,我現在完全明白爲什麼返回語句也是必要的 –

回答

3

當您在一個孩子叫total += data.pop()函數中,變量total在調用函數中未更改,因爲整數是不可變的。

在函數返回之前,只有第一個要彈出的元素1被添加到total。爲了做同樣的事情,你需要用return addition(data, total)替換addition(data, total)

+1

經過測試,你是正確的。當我再次調用函數時,我不知道正在創建副本。 –

+0

要清楚,變量'data'不會被複制,因爲它是一個列表,只有'total'。 – yinnonsanders

+0

@SzombatfalviHunorGellèrt呃..我其實認爲答案的一部分是錯誤的。沒有拷貝:'data = [1,2,3,1,2,1];印刷(除(數據)); print(data)'會打印一個空列表。 – kazemakase

2

結果與變量作用域無關。您的第一次執行將遞歸調用的結果返回到addition。第二個實現不。因此,total在第一個元素後沒有更新。

def addition(data, total=0): 
    if data != []: 
     total += data.pop() 
     # addition(data, total) # return value not used; this line does not modify result 
    return total # total = 0 + first element 

兩個函數pop都來自原始列表,因此修改了輸入數據。考慮這樣一種替代方案:

def addition(data, total=0): 
    if data: 
     return addition(data[1:], total + data[0]) 
    return total 
2

有疑問時,隨時添加打印語句;)

def addition(data, total=0): 
    if data!= []: 
     total += data.pop() 
     print("Total is " + str(total)) 
     addition(data, total) 
    return total 

addition([1,2,3])回報:

Total is 3 
Total is 5 
Total is 6 
3 

你看到那裏的錯誤是現在? :)你不會做任何事情,返回值爲addition(data, total) - 這段代碼沒有任何結果。你可以做的是返回此值:

def addition(data, total=0): 
    if data!= []: 
     total += data.pop() 
     return addition(data, total) 
    return total 

我們來分析一下這段代碼做什麼:如果data是空的 - 返回total - 我們添加的一切已經,沒有什麼關係。如果data不是一個空列表,它將從數據中彈出一個元素,將此值添加到total並使用較短的列表重複該過程。相信這段代碼確實是你想要的。