仅仅为了好玩,我基于Aaron的建议创建了一个前瞻类的实现:
import itertools
class lookahead_chain(object):
def __init__(self, it):
self._it = iter(it)
def __iter__(self):
return self
def next(self):
return next(self._it)
def peek(self, default=None, _chain=itertools.chain):
it = self._it
try:
v = self._it.next()
self._it = _chain((v,), it)
return v
except StopIteration:
return default
lookahead = lookahead_chain
有了这个,以下内容将会正常工作:
>>> t = lookahead(xrange(8))
>>> list(itertools.islice(t, 3))
[0, 1, 2]
>>> t.peek()
3
>>> list(itertools.islice(t, 3))
[3, 4, 5]
使用此实现连续多次调用peek是一个不好的主意...
我在查看CPython源代码时发现了一种更好的方法,既短又高效:
class lookahead_tee(object):
def __init__(self, it):
self._it, = itertools.tee(it, 1)
def __iter__(self):
return self._it
def peek(self, default=None):
try:
return self._it.__copy__().next()
except StopIteration:
return default
lookahead = lookahead_tee
使用方法与上面相同,但您不需要在此处支付任何费用以连续多次使用peek。通过添加几行代码,您还可以向前查看迭代器中超过一个项(最多可达可用RAM)。
gen.next()
。这就是异常StopIteration
的作用。在元素“STOP”之后生成器中有什么?为什么生成器在此时不会被简单地耗尽?或者,如果不可能,为什么不让生成器在当前元素为“Stop”时raise StopIteration
? - Tim Pietzcker