在以下代码中:
def listSum(alist):
"""Get sum of numbers in a list recursively."""
sum = 0
if len(alist) == 1:
return alist[0]
else:
return alist[0] + listSum(alist[1:])
return sum
是每次listSum(alist[1:])
时创建的新列表?
如果是,这是推荐的方式还是我可以做更高效的事情? (不是针对特定的功能 - 这是一个例子 - 而是当我想要处理一般列表的特定部分时。)
编辑:
很抱歉,如果我对任何人感到困惑,我对高效的sum
实施不感兴趣,这就是以这种方式使用切片的示例。
答案 0 :(得分:5)
是的,它每次都会创建一个新列表。如果您可以使用iterable,则可以使用itertools.islice
或juggle iter(list)
(如果您只需要在开始时跳过某些项目)。但是当你需要确定参数是空的还是只有一个元素时,这会变得混乱 - 你必须使用try
并捕获StopIteration
。编辑:您还可以添加一个额外的参数来确定从哪里开始。与@ marcadian的版本不同,你应该把它作为默认参数,不要给调用者带来负担,并避免从外部传入错误索引的错误。
通常最好不要陷入这种情况 - 编写代码以便让for
处理迭代(读取:不要像这样使用递归)。或者,如果切片相当小(可能是因为列表整体很小),无论如何咬住子弹和切片 - 它更容易,而切片是线性时间,常数因子非常小。
答案 1 :(得分:2)
我可以考虑一些选择:
选项2的工作方式如下:
def f_sum(alist, idx=0):
if idx >= len(alist):
return 0
return alist[idx] + f_sum(alist, idx + 1)
f_sum([1, 2, 3, 4])
a = range(5)
f_sum(a)
答案 2 :(得分:0)
如果必须使用递归(tail-recursive),这是另一种方法。在许多其他语言中,就空间复杂性而言,这比常规递归更有效。不幸的是,在python中并非如此,因为它没有内置支持来优化尾调用。如果您正在学习递归,那么注意这是一个很好的做法。
def helper(l, s, i):
if len(l) == 0:
return 0
elif i < len(l) - 1:
return helper(l, s + l[i], i + 1)
else:
return s + l[i]
def listSum(l):
return helper(l, 0, 0)