Python列表切片效率

时间:2013-08-26 01:06:12

标签: python list slice

在以下代码中:

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实施不感兴趣,这就是以这种方式使用切片的示例。

3 个答案:

答案 0 :(得分:5)

是的,它每次都会创建一个新列表。如果您可以使用iterable,则可以使用itertools.islice或juggle iter(list)(如果您只需要在开始时跳过某些项目)。但是当你需要确定参数是空的还是只有一个元素时,这会变得混乱 - 你必须使用try并捕获StopIteration。编辑:您还可以添加一个额外的参数来确定从哪里开始。与@ marcadian的版本不同,你应该把它作为默认参数,不要给调用者带来负担,并避免从外部传入错误索引的错误。

通常最好不要陷入这种情况 - 编写代码以便让for处理迭代(读取:不要像这样使用递归)。或者,如果切片相当小(可能是因为列表整体很小),无论如何咬住子弹和切片 - 它更容易,而切片是线性时间,常数因子非常小。

答案 1 :(得分:2)

我可以考虑一些选择:

  1. 对此特定情况使用内置函数和
  2. 如果你真的需要递归(由于某种原因),请将相同的列表传递给函数调用以及当前元素的索引,这样就不需要对列表进行切片(这会创建新列表)
  3. 选项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)