More baby squeaking - iterators in a class

Terry Reedy tjreedy at udel.edu
Fri Dec 31 21:44:54 EST 2004


"M.E.Farmer" <mefjr75 at hotmail.com> wrote in message 
news:1104511354.639920.246830 at c13g2000cwb.googlegroups.com...
> Terry Reedy wrote:
>>will. Try ip=iter(p) followed by ip.next and ip.next() instead.

> Does that mean if you dont't call iter(() on your instance or have a
> next() method you can't do this:

>>>>> p=R3('eggs')
>>>>> for i in p:
>>>>>    print i

Ignoring the older iteration method based on __getitem__, which I recommend 
you do ignore, yes, you cannot do that.

> I am asking because I want to fully understand what makes an
> *iterator*.

An iterator is an object with an __iter__ method that returns 'self' and a 
parameterless .next() method that on each call either returns an object or 
raises StopIteration.

An iterable is an object with an __iter__ method that returns an iterator.

A generator function (one containing yield in the code body), when called, 
returns a generator, which is a particular type of iterator.   So, a class 
with .__iter__ written as a generator function has iterable instances.

I can think of three reasons to go this latter route:
1. Writing a generator function may be easier that writing a standard 
function for .next.
2. The resulting iteration may be faster.
3. Iterating with a separate generator allows iteration without  disturbing 
the data of the instance (ie, non destructively).   This means that one can 
iterate more than once, even more than once at the same time.  Consider 
'multiplying' a sequence by itself:

  (i,j) for i in iterable for j in iterable

iter(iterable) is called once and then once again for each item yielded by 
the first call.

Terry J. Reedy






More information about the Python-list mailing list