2017-07-17 43 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并使用较短的列表重复该过程。相信这段代码确实是你想要的。