在Python中通过切片进行有效的迭代

发布于 2021-01-29 17:30:28

Python中切片操作的迭代效率如何?而且,如果不可避免地要有切片,那么有替代方法吗?

我知道列表上的切片操作为O(k),其中k是切片的大小。

x[5 : 5+k]  # O(k) copy operation

但是,当遍历列表的一部分时,我发现执行此操作的最简洁的方法(也是最Python的?)(不必求助于索引)是:

for elem in x[5 : 5+k]:
  print elem

但是,我的直觉是,这仍然会导致子列表的开销很大,而不是简单地遍历现有列表。

关注者
0
被浏览
50
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    您可以用来itertools.islice从列表中获取切片式迭代器:

    例:

    >>> from itertools import islice
    >>> lis = range(20)
    >>> for x in islice(lis, 10, None, 1):
    ...     print x
    ...     
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    

    更新:

    正如@
    user2357112所指出的那样,的性能islice取决于切片的起点和可迭代的大小,在几乎所有情况下,普通切片都将很快,因此应首选。以下是一些时序比较:

    对于 巨大的名单 islice是稍快或等于正常片时片的起点是列表中只有不到一半的大小,更大的指标正常切片是明显的赢家。

    >>> def func(lis, n):
            it = iter(lis)
            for x in islice(it, n, None, 1):pass
    ...     
    >>> def func1(lis, n):
            #it = iter(lis)
            for x in islice(lis, n, None, 1):pass
    ...     
    >>> def func2(lis, n):
            for x in lis[n:]:pass
    ...     
    >>> lis = range(10**6)
    
    >>> n = 100
    >>> %timeit func(lis, n)
    10 loops, best of 3: 62.1 ms per loop
    >>> %timeit func1(lis, n)
    1 loops, best of 3: 60.8 ms per loop
    >>> %timeit func2(lis, n)
    1 loops, best of 3: 82.8 ms per loop
    
    >>> n = 1000
    >>> %timeit func(lis, n)
    10 loops, best of 3: 64.4 ms per loop
    >>> %timeit func1(lis, n)
    1 loops, best of 3: 60.3 ms per loop
    >>> %timeit func2(lis, n)
    1 loops, best of 3: 85.8 ms per loop
    
    >>> n = 10**4
    >>> %timeit func(lis, n)
    10 loops, best of 3: 61.4 ms per loop
    >>> %timeit func1(lis, n)
    10 loops, best of 3: 61 ms per loop
    >>> %timeit func2(lis, n)
    1 loops, best of 3: 80.8 ms per loop
    
    
    >>> n = (10**6)/2
    >>> %timeit func(lis, n)
    10 loops, best of 3: 39.2 ms per loop
    >>> %timeit func1(lis, n)
    10 loops, best of 3: 39.6 ms per loop
    >>> %timeit func2(lis, n)
    10 loops, best of 3: 41.5 ms per loop
    
    >>> n = (10**6)-1000
    >>> %timeit func(lis, n)
    100 loops, best of 3: 18.9 ms per loop
    >>> %timeit func1(lis, n)
    100 loops, best of 3: 18.8 ms per loop
    >>> %timeit func2(lis, n)
    10000 loops, best of 3: 50.9 us per loop    #clear winner for large index
    >>> %timeit func1(lis, n)
    

    对于 小型列表, 普通切片比islice几乎所有情况下都快。

    >>> lis = range(1000)
    >>> n = 100
    >>> %timeit func(lis, n)
    10000 loops, best of 3: 60.7 us per loop
    >>> %timeit func1(lis, n)
    10000 loops, best of 3: 59.6 us per loop
    >>> %timeit func2(lis, n)
    10000 loops, best of 3: 59.9 us per loop
    
    >>> n = 500
    >>> %timeit func(lis, n)
    10000 loops, best of 3: 38.4 us per loop
    >>> %timeit func1(lis, n)
    10000 loops, best of 3: 33.9 us per loop
    >>> %timeit func2(lis, n)
    10000 loops, best of 3: 26.6 us per loop
    
    >>> n = 900
    >>> %timeit func(lis, n)
    10000 loops, best of 3: 20.1 us per loop
    >>> %timeit func1(lis, n)
    10000 loops, best of 3: 17.2 us per loop
    >>> %timeit func2(lis, n)
    10000 loops, best of 3: 11.3 us per loop
    

    结论:

    去正常切片。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看