Python列表切片效率

2024-05-16 01:02:42 发布

您现在位置:Python中文网/ 问答频道 /正文

在以下代码中:

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


Tags: of代码in示例列表getreturndef
3条回答

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

通常最好不要陷入这种情况——要么编写代码,让for处理迭代(读:不要使用这样的递归)。或者,如果切片相当小(可能是因为整个列表很小),那么无论如何都要咬紧牙关切片-这更容易,虽然切片是线性时间,但常数因子真的很小。

我能想到一些选择:

  1. 在这种特殊情况下使用内置函数sum
  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)

如果必须使用递归(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)

相关问题 更多 >