我通过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)没有要切片的范围。
当然如果n
是None
,那么我肯定会None
所以看来无论我在这里做什么,我都以None
作为输出,这个功能的用途是什么?
答案 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>