iterator.next() confusion

Steven Taschuk staschuk at telusplanet.net
Mon Jun 2 02:46:45 EDT 2003


Quoth Clark C. Evans:
> 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:
  [...]
> Code like the above seems to work with most iterables, however,
> it will get into an endless loop with the following iterator:
> 
>     class evilIterator:
  [...iterator for which calling self.next rebinds self.next...]

This kind of iterator actually fails in for loops if it is made
new-style.

> Which is incorrect use of the iterator PEP?  [...]

For new-style objects only type(it).next is used; whether it is
shadowed by an instance attribute doesn't matter.  So my feeling
is that using an instance-specific .next is not kosher, even
though it works for old-style iterators.  (Note that the PEP
speaks only of defining .next in the class.)

It is possible to write an evil new-style iterator, though:

    class NewEvilIterator(object):
        def __iter__(self):
            return self
        def next(self):
            NewEvilIterator.next = NewEvilIterator.next_stop
            return 1
        def next_stop(self):
            raise StopIteration()

This works, sort of.  Certainly a for loop looks up the .next
class attribute anew at each iteration.  Of course, as a real
technique this is useless; you can't have multiple independent
instances of such a class, even if their lifetimes don't overlap.

I can't think of a way to write a usable new-style iterator class
which breaks under caching of .next.

-- 
Steven Taschuk                                     staschuk at telusplanet.net
Receive them ignorant; dispatch them confused.  (Weschler's Teaching Motto)





More information about the Python-list mailing list