Skip to content

Instantly share code, notes, and snippets.

@Olian04
Created November 23, 2016 15:01
Show Gist options
  • Save Olian04/616439e94dc2bb85da3102197b6e734f to your computer and use it in GitHub Desktop.
Save Olian04/616439e94dc2bb85da3102197b6e734f to your computer and use it in GitHub Desktop.
null created by Olian04 - https://repl.it/E6UU/2
from PeekIter import PeekIter
print("Using a while loop")
foo = PeekIter(i for i in range(10))
while foo:
print("Next: {}\t\tPeek: {}".format(foo.next, foo.peek))
print("Using a for loop")
foo = PeekIter(i for i in range(10))
for _next in foo:
print("Next: {}\t\tPeek: {}".format(_next, foo.peek))
print("Using recursion")
foo = PeekIter(i for i in range(10))
def bar():
print("Next: {}\t\tPeek: {}".format(foo.next, foo.peek))
if foo:
bar()
bar()
"""
[PeekIter]: Wrapper class for iterators, implements peeking.
"""
__VERSION = "0.1"
__AUTHOR = "Olian04"
class PeekIter:
"""PeekIter wrapper class, adds peek, done and next functionality to an iter.
[iterator]: The iterator to wrap.
- In v0.1 the iterator may NOT produce None results.
None is used internaly to signal end of data.
"""
def __init__(self, iterator):
self._iter = iter(iterator)
self._peeked = None
def __repr__(self):
return "PeekIter(done={done}, next='{next}', inner='{inner}')".format(
next=self.peek,
done=self.done,
inner=type(self._iter))
def __bool__(self):
"Returns True while there are more elements available from the generator"
return not self.done
def __next__(self):
return self.next
def __iter__(self):
"Yields every element in the iterator, then raises StopIteration."
while not self.done:
yield self.next
raise StopIteration
@property
def next(self):
"Get the next value from the generator."
if self._peeked != None:
val, self._peeked = self._peeked, None
return val
return self._try_next()
@property
def peek(self):
"Peek at the next value from the generator."
if self._peeked != None:
return self._peeked
self._peeked = self._try_next()
return self._peeked
@property
def done(self):
"Returns true if the next value in the iterator is equal to the terminal_token."
return self.peek == None
def _try_next(self):
"Returns the next item from the iterator or, if that fails, returns the terminal_token."
try:
return next(self._iter)
except StopIteration:
return None
def fork(self):
"""Forks the generator as is, i.e. in its current state.
[WARNING]: This utelizes itertools.tee, which makes PeekIter.fork() a highly demanding operation.
Do NOT use this operation unless absolutely nessessary.
"""
from itertools import tee
_iters = tee(self._iter)
self._iter = _iters[0]
return PeekIter(_iters[1])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment