reseting an iterator

Terry Reedy tjreedy at
Fri May 22 00:21:37 CEST 2009

I will clarify by starting over with current definitions.

Ob is an iterator iff next(ob) either returns an object or raises 
StopIteration and continues to raise StopIteration on subsequent calls.

Ob is an iterable iff iter(ob) raturns an iterator.

It is intentional that the protocol definitions be minimal, so that they 
can used as widely as possible.

As a convenience, the definition of iterators is given a slight 
complication.  They are defined as a subcategory of iterables, with the 
  requirement that iter(iterator) be that same iterator.  This means 
that iterators need the following boilerplate:
   def __iter__(self): return self
The extra burden is slight since most iterators are based on builtins or 
generator functions or expressions, which add the boilerplate 
automatically.  The convenience is that one may write

def f(iterable_or_iterator):
   it = iter(iterable_or_iterator)

instead of

def f(iterable_or_iterator):
   if is_iterable(iterable_or_iterator):
     it = iter(iterable_or_iterator)
     it = iterable_or_iterator

In particular, the internal function that implements for loops can do 
the former.

In other words, a small bit of boilerplate added to iterators, mostly 
automatically, saves boilerplate in the use of iterators and iterables.

When the protocols were defined, there was discussion about whether or 
not to require 'continue to raise StopIteration'.  For instance, an 
iterator that returns objects derived from external input might not have 
any new external input now but expect to get some in the future.  It was 
decided the such iterators should either wait and block the thread or 
return a 'Not now' indicator such as None.  StopIteration should 
consistently mean 'Done, over and out' so for loops, for instance, would 
know to exit.

The OP proposes that StopIteraton should instead mean 'Done until 
reset', without defining 'reset'.  Some comments:
* This would complicate the protocol.
* There are real use cases, and reiterability is a real issue.  But ...
* Depending on the meaning, resetting may or may not be possible.
* When it is possible, it can potentially be done today with a .send() 
* Many use cases are easier with a new iterator.  For instance

for i in iterable: block1()
for i in iterable: block2()

is easier to write than

it = iter(iterable)
for i in it: block1()
for i in it: block2()

with little relative time saving in the second case, for practical 
problems, to compensate for the extra boilerplate.

Terry Jan Reedy

More information about the Python-list mailing list