Просто для забавы я создал реализацию преднамеренного класса на основе предложения
Аарон:
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 много раз подряд. Имея еще несколько строк, вы также можете просмотреть несколько элементов в итераторе (вплоть до доступной оперативной памяти).