[Python-Dev] Termination of two-arg iter()

Guido van Rossum guido@python.org
Mon, 15 Jul 2002 11:15:58 -0400


I'm still only considering two options:

  (a) leave the status quo, or
  (b) implement (and document!) the "sink-state" rule from the PEP.

If we end up adopting (b), what can we do to Python 2.2 that doesn't
break the "bug-fixes-only" promise of that branch?

If there's code that depends on the extendibility of list iterators,
are we breaking our promise by breaking that code?

OTOH, I just noticed that the general sequence iterator has a
different behavior than the list iterator (both in 2.3 and in 2.2):
the general sequence iterator increments its index before checking for
IndexError, while the list iterator only increments when it knows
it's got a valid item.  That means that if you use the general list
iterator over an extensible sequence, you miss an item!

-----------------------------
class Seq:
    def __init__(self, n):
        self.n = n
    def __getitem__(self, i):
        if 0 <= i < self.n:
            return i
        else:
            raise IndexError
a = Seq(3)
it = iter(a)
for i in it:
    print i,
a.n = 5
for i in it:
    print i,
-----------------------------

This prints "0 1 2 4".  This is sufficiently braindead that we can
assume that *if* this behavior is relied upon, it's only for lists.

Still, the question is, could "fixing" the list iterator in 2.2.2
become a problem?

I'd like to think that more people are surprised by this behavior than
rely on it, but I'm not sure.

A simple fix for the sequence and dict iterators is to let a negative
index signal exhaustion.  A simple fix for the callable iter is to set
the callable to NULL to signal exhaustion.  (Setting the main object
to NULL could also work for the others, actually, and has the added --
minuscule -- advantage of releasing a reference early.)

--Guido van Rossum (home page: http://www.python.org/~guido/)