Iterator / Iteratable confusion

Terry Reedy tjreedy at udel.edu
Mon Feb 14 20:26:42 EST 2005


"Francis Girard" <francis.girard at free.fr> wrote in message 
news:200502142131.53265.francis.girard at free.fr...

(Note for oldtimer nitpickers: except where relevant, I intentionally 
ignore the old and now mostly obsolete pseudo-__getitem__-based iteration 
protocol here and in other posts.)

Le dimanche 13 Février 2005 23:58, Terry Reedy a écrit :
>> Iterators are a subgroup of iterables. Being able to say iter(it) 
>> without
>> having to worry about whether 'it' is just an iterable or already an
>> iterator is one of the nice features of the new iteration design.

>I have difficulties to represent an iterator as a subspecie of an 
>iteratable

You are not the only one.  That is why I say it in plain English.

You are perhaps thinking of 'iterable' as a collection of things.  But in 
Python, an 'iterable' is a broader and more abstract concept: anything with 
an __iter__ method that returns an iterator.

To make iterators a separate, disjoint species then requires that they not 
have an __iter__ method.  Some problems:
A. This would mean either
    1) We could not iterate with iterators, such as generators, which are 
*not* derived from iterables, or, less severely
    2) We would, usually, have to 'protect'  iter() calls with either 
hasattr(it, '__iter__') or try: iter(it)...except: pass with probably no 
net average time savings.
B. This would prohibit self-reiterable objects, which require .__iter__ to 
(re)set the iteration/cursor variable(s) used by .next().
C. There are compatibility issues not just just with classes using the old 
iteration protocol but also with classes with .next methods that do *not* 
raise StopIteration.  The presence of .__iter__ cleanly marks an object as 
one following the new iterable/iterator protocol.  Another language might 
accomplish the same flagging with inheritance from a base object, but that 
is not Python.

> [snip]...C++ STL where there is a clear (I resist to
> say "clean") distinction between iteratable and iterator.

leaves out self-iterating iterables -- collection objects with a .next 
method.  I am sure that this is a general, standard OO idiom and not a 
Python-specific construct.  Perhaps, ignoring these, you would prefer the 
following nomenclature:
iterob   = object with .__iter__
iterable= iterob without .next
iterator = iterob with .next

Does STL allow/have iterators that are *not* tied to an iterable?

>One of the result of not distinguishing them is that, at some point in 
>your
>programming, you are not sure anymore if you have an iterator or an
>iteratable ; and you might very well end up calling "iter()" or
> "__iter__()" everywhere.

If you iterate with a while loop just after creating a new iterable or 
iterator, then you probably do know which it is and can make the iter() 
call only if needed.  If you while-iterate with a function argument, then 
iter() is a simpler way to be generic than the alternatives in A2 above.

>I am not concerned with the small performance issue involved here

Good.  I think there are small.  The number and time for iterations is far 
more important.

> (as I very seldom am) but with clarity. After all, why should you have to 
>  > call __iter__ on an iterator you just constructed

As I said above, you don't, and most people wouldn't.  The function 
implementing for loops does because *it*, unlike you, only sees the object 
passed and not the code that created the object!

>I have a strong feeling that the problem arises from the difficulty to
> marry the familiar ""for ... in ..."" construct with iterators. [snip]

What difficulty?  For loops accept an iterable and iterate with the derived 
iterator.

Would you really prohibit the use of for loops with generators and other 
non-iterable-derived iterators?  See A1 above.

>To have iterators act as iteratables might very well had been a 
> >compromise to solve the problem.

I think it elegant.  See below.

>I am not sure at all that this is a "nice feature" to consider an iterator 
>at
>the same level that an iteratable.

I think you are too stuck in the STL model.

> It makes it a bit more akward to have the
>"mind impulse", so to speak, to build iterators on top of other iterators 
>to > slightly modify the way iteration is done.

On the contrary, what could be more elegant than
def itermodifier(it):
  for i in it: # where it is often an iterator
     yield modification-of-i
See the itertools module and docs and the examples of chaining iterators.

Terry J. Reedy






More information about the Python-list mailing list