Iterator / Iteratable confusion

Terry Reedy tjreedy at udel.edu
Mon Feb 14 23:19:28 EST 2005


"Michael Spencer" <mahs at telcopartners.com> wrote in message 
news:cuooip$1pd$1 at sea.gmane.org...
> Terry Reedy wrote:
>> iter(iterator) is iterator is part of the iterater protocol

> But, notwithstanding the docs, it is not essential that
> iter(iterator) is iterator

If a program depends on that invariant, then it is essential for that 
program.  Leaving such programs aside, I interpret this and your example 
together as saying three things:

1. "There is more than one possible definition of 'iterator'."

Yes.  Python could have defined many things differently.  But I think it 
important to have a clear definition of iterator (and other things) so one 
can reason about program behavior.

2. "It is not essential to not do something wasteful as long as it is 
otherwise inconsequential."

Usually true, but I don't see this as clarifying the relationship between 
iterables and iterators in Python.  (I am assuming that your example is 
only meant to illustrate possibilities rather than usefulness.)

3. "You can substitute a copy of an object that is never mutated for the 
object itself."

True, as long as you do not look at the id.  But in practice, change of 
state is essential to the function of nearly all iterators.  For mutated 
objects, one has to add the proviso that the copy is current and the 
substitution total, so that there are no references left to the original. 
But again, this has nothing in particular to do with iteration.

>  >>> class A(object):
>  ...     def __iter__(self):
>  ...         return AnIterator()
>  ...
>  >>> class AnIterator(object): # an iterator that copies itself

By the narrower definition of iterator that I used, this is not an 
iterator.  Also, the replacement is only a copy if the instance has not 
been mutated.  Is your broader definition limited to return of initialized 
copies or would it allow other things also?

>  ...     def next(self):
>  ...         return "Something"
>  ...     def __iter__(self):
>  ...         return AnIterator()

The second def statement is equivalent (except for identity) to
    __iter__ = A.__iter__

To illustrate the point about mutation with a simple toy example:

a = A()
a.doc = 'My iterator'
b = iter(a)

b is not a copy of a as it is, but only as it was initially.

Terry J. Reedy






More information about the Python-list mailing list