iterator.next() confusion

Hans Nowak zephyr01 at alltel.net
Thu May 29 16:52:04 EDT 2003


Clark C. Evans wrote:
> Hello all.  The iterator PEP doesn't seem to say if the next() method
> of the iterator could be cached during a loop, for example:
> 
>     def printall( iterable ):
>         next = iter( iterable ).next
>         try:
>             while 1:
>                 print next()
>         except StopIteration: 
>             pass
> 
> Code like the above seems to work with most iterables, however,
> it will get into an endless loop with the following iterator:
> 
>     class evilIterator:
>         def __init__(self):
>             self.next = self._next_one
>         def __iter__(self):
>             return self
>         def _next_one(self):
>             self.next = self._next_two
>             return "one"
>         def _next_two(self):
>             self.next = self._next_stop
>             return "two"
>         def _next_stop(self):
>             raise StopIteration

Indeed, an endless loop, because

 >         next = iter( iterable ).next

"caches" self.next, which at that time happens to be the same as 
self._next_one.  After calling self._next_one, self.next is rebound, but this 
does not affect your next variable, which still refers to self._next_one. 
Hence the idle loop.

> Which, of course, works just fine in:
> 
>     def printall( iterable ):
>         for itm in iterable:
>             print itm

In this case, self.next() is called implicitly, so all the rebindings work 
fine.  No cache here.

> Which is incorrect use of the iterator PEP?  The former or the latter?
> If it is the former, why was this done, as it seems storing the function
> would save a dictionary lookup on each iteration.  The latter, while a
> cute implementation of a state machine, could be done other ways.

I don't think it has much to do with the PEP.  This behavior is not 
specifically related to iterators, it would be the same with any method that 
you would 'cache' this way and then rebind.

Cheers,

--Hans







More information about the Python-list mailing list