How to unget a line when reading from a file/stream iterator/generator?

Arnaud Delobelle arnodel at googlemail.com
Mon Apr 28 14:42:50 EDT 2008


python at bdurham.com writes:

> Is there an elegant way to unget a line when reading from a file/stream
> iterator/generator?
>
> By "unget" I mean a way to push back a line into the source stream and
> backtrack the iterator/generator one step?
>
> The only alternative I can see is to put my line reading in a while-True
> loop (vs. a for-loop) that manually calls my file/stream
> iterator/generator's .next() method while manually handling the
> StopIteration exception. Doesn't sound too elegant.
>
> Is there a Pythonic design pattern/best practice that I can apply here?

It seems to me that the answer depends on what you do with your
unget'ed line (i.e. there is no included general purpose 'unget'
replacement).  If you provided some (pseudo-)code, someone might be
able to find an elegant way to perform the task without the need to
push back an element into an iterator.

As a last resort, you could always wrap your iterator into a some
'Backtrackable' class.

class Backtrackable(object):
      def __init__(self, iterator):
          self.iterator = iter(iterator)
          self._back = False
          self._last = None
      def __iter__(self):
          return self
      def next(self):
          if self._back:
              next = self._last
          else:
              self._last = next = self.iterator.next()
          self._back = False
          return next
      def back(self):
          if self._back:
              raise('Cannot backtrack twice')
          self._back = True

>>> b = Backtrackable([1,2,3])
>>> b.next()
1
>>> b.next()
2
>>> b.back()
>>> b.next()
2
>>> b.next()
3



More information about the Python-list mailing list