Для розваги я створив реалізацію класу lookahead на основі пропозиції Аарона:
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
Використання таке саме, як і вище, але тут ви не заплатите ціну, щоб використовувати підглядання багато разів поспіль. Маючи ще кілька рядків, ви також можете заглянути вперед більше одного елемента в ітераторі (до доступної оперативної пам'яті).