python itertools Recipe Consumer() 到底是什么意思?

Cod*_*755 1 python iterator

我正在通过 python 文档学习 itertools:

https://docs.python.org/3/library/itertools.html

最后有一些使用 itertools 命令来做简单事情的食谱,其中之一是 Consumer(),我根本不明白它:

from itertools import *
def consume(iterator, n):
    """"Advance the iterator n-steps ahead. If n is none, consume 
        entirely."""
    if n is None:
        # feed the entire iterator into a zero-length deque
        collections.deque(iterator, maxlen=0)
    else:
        # advance to the empty slice starting at position n
        next(islice(iterator, n, n), None)
Run Code Online (Sandbox Code Playgroud)

首先,这个函数声称参数是一个迭代器,但我发现可迭代也可以。我认为可迭代和迭代器之间有区别,对吗?因为islice()不需要迭代器,所以可以使用迭代器

其次,当我尝试时:

aa = iter([1,2,3,4,5])
print(consume(aa, 2))
Run Code Online (Sandbox Code Playgroud)

它给了我None,因为islice(iterator, n, n)无论如何都会如此None,因为 (n, n) 没有要切片的范围。

当然,如果nNone,那么我肯定会得到None 所以看起来无论我在这里做什么,我都会得到None输出,这个函数的目的到底是什么?

Bre*_*arn 5

consume不应该返回任何有用的东西。正如文档所说,它的目的是推进现有的迭代器。如果您查看aa示例,您会发现它已被高级:

>>> aa = iter([1,2,3,4,5])
... print(consume(aa, 2))
None
>>> next(aa)
3
Run Code Online (Sandbox Code Playgroud)

因为使用它consume是有副作用的,所以你可以在一个“可重迭代”的对象上使用它,但这样做是没有用的。发生的情况是,islice将在该对象上创建一个迭代器,并推进该迭代器,但这不会影响该可迭代对象的后续迭代,因为将创建一个新的迭代器:

# consuming an iterator
aa = iter([1,2,3,4,5])
consume(aa, 2)
print(list(aa))
# [3, 4, 5]

# "consuming" an iterable
aa = [1,2,3,4,5]
consume(aa, 2)
print(list(aa))
# [1, 2, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)

在后一种情况下,您消耗的只是一个在自身内部创建consume但未返回的临时迭代器,因此它没有可观察到的效果。

(我使用术语“可重迭代”来指代可迭代对象,这些对象每次iter调用时都会在一些稳定的基础数据上生成“新鲜”迭代器。例如,列表是可重迭代的。每个可重迭代对象都是可迭代的,但你可以编写一个不可重复迭代的可迭代对象。)