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 -- http://mail.python.org/mailman/listinfo/python-list