python itertools recipe消耗()意味着什么?

时间:2017-11-25 19:58:41

标签: python iterator

我通过python docs学习了itertools:

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

最后有一些配方使用itertools命令来做简单的事情,其中​​之一就是consume(),我根本不理解它:

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)

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

其次,当我尝试时:

aa = iter([1,2,3,4,5])
print(consume(aa, 2))

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

当然如果nNone,那么我肯定会None 所以看来无论我在这里做什么,我都以None作为输出,这个功能的用途是什么?

2 个答案:

答案 0 :(得分:4)

consume不应该返回任何有用的东西。就像文档所说,它的目的是推进现有的迭代器。如果您在示例后查看aa,您会看到它已被提升:

>>> aa = iter([1,2,3,4,5])
... print(consume(aa, 2))
None
>>> next(aa)
3

因为使用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]

在后一种情况下,你所消耗的只是一个临时迭代器,它是在consume本身内创建的,但没有返回,所以它没有可观察到的效果。

(我使用术语"可重复使用"引用可迭代对象,每次调用iter时,它们会生成一些"新的"迭代器,而不是某些稳定的基础数据。例如,列表是可重复的迭代。每个可重复的对象都是可迭代的,但是你可以编写一个不可重复的可迭代对象。)

答案 1 :(得分:2)

通过列表迭代是没有意义的,除非你对它的元素做了一些事情,但是通过迭代器前进可以执行代码;例如,您可能正在迭代具有副作用的函数返回的值。 consume()遍历几个元素并抛弃它们。一般的想法(如果你不消耗所有东西)是它在文件句柄中的工作方式就像seek():当你试图从迭代器中取出一些东西时,你将处于不同的位置。 / p>