
Hi, Several people have felt the need to be able to 'peek ahead' for the next value of an iterator without actually retrieving it. I have, and I have a 'peekable' class that I use to wrap around iterators when I need this feature:
There is an example of implementation at: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/304373 A wrapper works fine but a lot of built-in iterators such as listiterators, tupleiterators, dictionary-***iterators could provide a peek() method natively, which would be much more efficient and would not necessitate any buffering. (e.g. in the case of a listiterator, peek() would be the same as next() but without incrementing the it_index counter) My idea is the following : * iterators such as the ones listed above, where providing a peek() method does not require any buffering or extra bookkeeping, implement this method natively. * for the other ones, no peek() method but a user can still wrap them as in the example above. * to provide a common interface, define a peekable class like this: class peekable(object): def __new__(cls, iterator): # if the iterator is already 'peekable', return it # otherwise wrap it if hasattr(iterator, 'peek'): return iterator else: return object.__new__(cls) def __init__(self, iterator): ... def __iter__(self): return self def next(self): ... def peek(self): ... This means that an iterator would have the option of providing a peek() method, but wouldn't have to. However all iterators could be made peekable by writing it = peekable(it) -- Arnaud

Arnaud Delobelle wrote:
I thought maybe the new .send() method might be good for this, but it's wasn't at all obvious how to do it. (I'm still not sure if this is correct and doesn't have weird behaviors.) Note: While writing this I came across the following error... is there a way we can get rid of this silly requirement? TypeError: can't send non-None value to a just-started generator def insert_iter(it): """ An insertable iterator. it.send(value) -> puts value in the iterator. """ it = iter(it) buff = [] while 1: if buff: nv = yield buff.pop(0) else: nv = yield it.next() while nv: buff.append(nv) nv = yield nv it = insert_iter('python') print (it.send(it.next()), # send it back, so it is avialable again. it.send(it.next()), it.next(), it.send(it.next()), it.next(), it.next()) PRINTS: ('p', 'p', 'p', 'y', 'y', 't') # Output of one iterator inserted into another # with extra content added. it2 = insert_iter([0]) # Needs at least one item it2.next() # to avoid silly error. :( for c1 in 'Hello world.': it2.send(c1) if c1 == ' ': for c2 in 'python ': it2.send(c2) print ''.join(it2) PRINTS: Hello python world.

Arnaud Delobelle wrote:
I thought maybe the new .send() method might be good for this, but it's wasn't at all obvious how to do it. (I'm still not sure if this is correct and doesn't have weird behaviors.) Note: While writing this I came across the following error... is there a way we can get rid of this silly requirement? TypeError: can't send non-None value to a just-started generator def insert_iter(it): """ An insertable iterator. it.send(value) -> puts value in the iterator. """ it = iter(it) buff = [] while 1: if buff: nv = yield buff.pop(0) else: nv = yield it.next() while nv: buff.append(nv) nv = yield nv it = insert_iter('python') print (it.send(it.next()), # send it back, so it is avialable again. it.send(it.next()), it.next(), it.send(it.next()), it.next(), it.next()) PRINTS: ('p', 'p', 'p', 'y', 'y', 't') # Output of one iterator inserted into another # with extra content added. it2 = insert_iter([0]) # Needs at least one item it2.next() # to avoid silly error. :( for c1 in 'Hello world.': it2.send(c1) if c1 == ' ': for c2 in 'python ': it2.send(c2) print ''.join(it2) PRINTS: Hello python world.
participants (2)
-
Arnaud Delobelle
-
Ron Adam