iterators: class vs generator

Clark C. Evans cce at clarkevans.com
Tue Aug 24 18:06:52 EDT 2004


There is an interesting difference between how exceptions are handled
between iterators constructed from a class, and iterators constructed
from a generator.  The following are "mostly equivalent":

      class iterable_via_class:
          def __iter__(self):
              self._next = self._one
              return self
          def next(self):
              return self._next()
          def _one(self):
              self._next = self._two
              return "one"
          def _two(self):
              self._next = self._stop
              return "two"
          def _stop(self):
              raise StopIteration()
          
      def iterable_via_generator():
          yield "one"
          yield "two"

      print "\nclass:"
      for x in iterable_via_class():
          print x

      print "\ngenerator:"
      for x in iterable_via_generator():
          print x

However, when exceptions are involved, behavior can be different:

      class iterable_via_class:
          def __iter__(self):
              self._next = self._one
              return self
          def next(self):
              return self._next()
          def _one(self):
              self._next = self._raise
              return "one"
          def _raise(self):
              self._next = self._two
              raise Exception()
          def _two(self):
              self._next = self._stop
              return "two"
          def _stop(self):
              raise StopIteration()
 
      def iterable_via_generator():
          yield "one"
          raise Exception()
          yield "two"

      def test(itergen):
          it = iter(itergen())
          print it.next()
          try:
             ignore = it.next()
          except:
             pass
          print it.next()

      print "\nclass:"
      test(iterablex)
      print "\ngenerator:"
      test(iterable)



More information about the Python-list mailing list