【问题标题】:Why this way for the recursion and what does it mean? [duplicate]为什么以这种方式进行递归,这意味着什么? [复制]
【发布时间】:2016-04-26 07:39:40
【问题描述】:

我正在尝试理解这段代码

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:])

【问题讨论】:

  • 1.参见docs.python.org/3/library/stdtypes.html#truth-value-testing,它是“如果ls 为空”的成语。 2. 如果你将整个列表(ls[0:] 或只是ls[:])传递给递归调用,它怎么会变成空的?
  • 谢谢@jonrsharpe。我应该结束我的问题吗?
  • 空容器是False
  • @jonrsharpe 感谢语法修正和删除 hard time ;)

标签: python


【解决方案1】:

想象一下它被称为...

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])

然后listSum([7])7 + listsum([]),这是not ls 开始并返回0 的地方。

所以,完整的东西然后被评估为......

3 + 5 + 3 + 7 + 0

注意事项:

  • listSum(ls[1:]) 每次都在缩短列表 - 降低剩余问题的复杂性,直到调用 listSum 收到一个空列表:if not ls: return 0 处理的小例子

    李>
  • 递归解决方案通常由两部分组成:最简单的可能输入的解决方案(或者有时是几个非常简单的情况),以及如何获取任意复杂的输入并将其简化为公式进行一个或多个递归调用,每个调用都至少简单一点,总是朝着最简单的输入方向前进

  • “我已经尝试使用 listSum(ls[0:]) - ls[0:] 返回 ls 的副本 - 它会要求无限处理相同的列表

  • 可以说,显式处理一个元素的列表更直观 - if len(ls) == 1: return ls[0] - 但是如果有人打电话给listSum([]),你会尝试访问[0](在if下面的其他代码中) 并引发异常;处理空列表使函数更易于使用 if listSum([]) 返回 0 对您的应用程序来说是明智的,但另一方面,让 listSum([]) 引发异常可能会发现列表意外出现的错误空 - 你可以决定哪个对你更有用;如果您确实处理了空列表情况,那么很高兴len(ls) == 1 情况下“正常工作”使用相同的递归逻辑

【讨论】:

  • 嗨@tony-d,假设我很愚蠢,我想继续携带listSum(ls[0]:),我会阻止我这样做吗?
  • @AndyK 系统递归限制?同样,如果您不缩短每个递归调用的列表,则永远不会达到空列表的终止条件。
  • 嗨@AndyK - 递归调用确实需要一些方法来知道何时停止,否则它们会挂起程序或在堆栈耗尽时崩溃,正如 jonrsharpe 提到的那样。
  • @TonyD 非常感谢您的时间和耐心。你完全解决了我的问题。荣誉
  • @AndyK:不客气。递归会引起很多人的注意-有时我也是-所以如果我为任何人节省了一点悲伤,那就太好了。干杯。
猜你喜欢
  • 1970-01-01
  • 2020-05-31
  • 2014-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多