What makes an iterator an iterator?
Terry Reedy
tjreedy at udel.edu
Wed Apr 18 22:38:30 EDT 2007
An iterator is an object with a .__iter__ method that returns self and a
.next method that either returns an object or raises StopIteration.
One very good way to get an iterator from an iterable is for .__iter__ to
be a generator function. When called, it returns an generator with
.__iter__ and .next methods that work as specified.
words = "Norwegian Blues have beautiful plumage!".split()
print words
prints
['Norwegian', 'Blues', 'have', 'beautiful', 'plumage!']
class Parrot(object):
def __init__(self, words):
self.words = words
def __iter__(self):
for word in words:
yield word
for word in Parrot(words):
print word
prints
Norwegian
Blues
have
beautiful
plumage!
One can also make an iterable an (self) iterator by correctly writing the
two needed methods.
class Parrot2(object):
def __init__(self, words):
self.words = words
def __iter__(self):
self.it = -1
return self
def next(self):
self.it += 1
try:
return self.words[self.it]
except IndexError:
raise StopIteration
for word in Parrot2(words):
print word
which prints the same 5 lines. However, when an object is its own
iterator, it can only be one iterator at a time (here, pointing at one
place in the word list), whereas the first method allows multiple iterators
(here, possibly pointing to different places in the list.
| Can you explain some of the details of why this code fails:
[snip all examples of bad code that violate the iterator rule by improperly
writing .next as a generator function]
I think most people should learn how to write iterators correctly, as I
gave examples of above, rather than worry about the details of how and why
mis-written code fails with a particular version of a particular
implementation. So I won't go down that road.
Terry Jan Reedy
More information about the Python-list
mailing list