【问题标题】:Why would I want to use itertools.islice instead of normal list slicing?为什么我要使用 itertools.islice 而不是普通的列表切片?
【发布时间】:2015-11-17 07:18:49
【问题描述】:

在我看来itertools 模块中的许多函数都有更简单的等效项。例如,据我所知,itertools.islice(range(10),2,5)range(10)[2:5] 做同样的事情,itertools.chain([1,2,3],[4,5,6])[1,2,3]+[4,5,6] 做同样的事情。主文档页面提到了速度优势,但除此之外还有什么理由选择 itertools?

【问题讨论】:

  • 他们并没有真正做同样的事情。 itertools.islice()、range() 和 itertools.chain() 返回不同的对象。最后,这些对象的行为相同,但在您的情况下,如果速度很重要,我会考虑比较字节码。

标签: python list iterator


【解决方案1】:

你可以用 vanilla python 做到这一点

In [64]: iterator = (x**2 for x in range(10))

In [65]: [x for i, x in enumerate(iterator) if i>=2 and i<5]
Out[65]: [4, 9, 16]

【讨论】:

    【解决方案2】:

    解决你提出的两个例子:

    import itertools
    
    
    data1 = range(10)
    
    # This creates a NEW list
    data1[2:5]
    
    # This creates an iterator that iterates over the EXISTING list
    itertools.islice(data1, 2, 5)
    
    
    data2 = [1, 2, 3]
    data3 = [4, 5, 6]
    
    # This creates a NEW list
    data2 + data3
    
    # This creates an iterator that iterates over the EXISTING lists
    itertools.chain(data2, data3)
    

    您想要使用迭代器而不是其他方法的原因有很多。如果列表非常大,则创建包含大型子列表的新列表可能会出现问题,或者特别是创建一个包含其他两个列表副本的列表。使用islice()chain() 允许您以您想要的方式迭代列表,而无需使用更多内存或计算来创建新列表。此外,正如unutbu 所提到的,您不能在迭代器中使用括号切片或加法。

    我希望这是一个足够的答案;还有很多其他答案和其他资源可以解释为什么迭代器很棒,所以我不想在这里重复所有这些信息。

    【讨论】:

    • 还值得一提的是,itertools.chain 可以接受许多参数来将任意数量的列表链接在一起,而使用 + 运算符则无法做到这一点。例如。 itertools.chain(*arbitrary_list_of_lists)
    • @veggie1,您可以+ 多个列表。不过最好使用itertools.chain(),或者如果需要存储它,可以使用list.extend() 构建一个列表。
    • 可以,但不能用于任意或未知数量的列表,除非你使用带有operator.add的循环
    • @veggie1,好吧..sum(([1, 2, 3], [4, 5, 6], [7, 8, 9]), [])。或者,sum(arbitrary_list_of_lists, [])。 :D
    • @veggie1,好点,我明白你的意思。我并不是真的很固执:P。
    【解决方案3】:

    itertools.islice 可以对iterators 进行切片。 索引仅适用于 sequences。 例如,

    In [64]: iterator = (x**2 for x in range(10))
    
    In [65]: list(IT.islice(iterator, 2, 5))
    Out[65]: [4, 9, 16]
    
    In [66]: iterator[2:5]
    TypeError: 'generator' object has no attribute '__getitem__'
    

    【讨论】:

    • 感谢您的快速回复。
    • 另外,即使对于列表,islice 也不会创建新列表,而常规列表切片会。
    • @BrenBarn 另一方面,islice 将遍历列表中的0..start 元素,而列表切片会跳过这些元素并直接转到start。也许另一种选择是(xs[i] for i in range(start, stop))
    猜你喜欢
    • 2023-02-09
    • 1970-01-01
    • 2014-07-18
    • 2011-03-24
    • 2011-12-26
    • 2015-08-22
    • 2011-05-12
    • 2019-04-19
    • 1970-01-01
    相关资源
    最近更新 更多