2016-04-26 77 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提到堆栈耗尽时,它们会挂起程序或崩溃。 –