[Python-ideas] iterable: next() and __iter__() -- and __reset()

Chris Rebert pyideas at rebertia.com
Thu Mar 4 12:45:11 CET 2010

On Thu, Mar 4, 2010 at 2:35 AM, spir <denis.spir at gmail.com> wrote:
> Hello,
> (1) I do not understand an iterable type's __iter__() method to be compulsary. Actually, each time I have defined one, I had to write:
>    def __iter__(self):
>        return self
> So, I guess that if python does not find __iter__(), but the object defines next(), then by default the said object could be used as its own iterator. This is what I understand by "iterable" and next() is the required method for it.
> Or even better: only if the object does not define next(), then python falls back to looking for __iter__(). Is there any obstacle for this I cannot see?

Not that I can think of; Python just happened to make a different
design decision than you, one that simplifies (and likely speeds up)
the interpreter at the minor cost of having to write a trivial "return
self" __iter__() in some cases: the interpreter can just blindly call
__iter__() as opposed to (as you suggest) doing more sophisticated
checking for a next() method and only then falling back to __iter__().

> Side-question: In which cases is it necessary to define the iterator as a separate object?

Whenever you want to use multiple iterators over the same object
simultaneously (you can usually equally use a generator instead of an
object, but the iterator is separate from the iterate-ee in either
case). For example, if lists were their own iterators, the following

for item1 in some_list:
    for item2 in some_list:
        print item1, item2

rather than outputting the cross-product of the items in the list,
would presumably instead output the first element paired with every
other element in the list, which is not what was intended.

> (2) But: for any reason next() is not spelled as a "magic" method. If this method becomes the distinctive method of iterables, then it should be called __next__() for consistency.

Guido's time machine strikes again! This is fixed in Python 3.x:

> (3) What I miss actually for iterables (which are their own iterator) is a kind of __reset__(). In some cases, it is only needed to allow a new iteration from start. But it may even be needed to set some startup data the first time. __reset__() would thus be called once before the first call to next().

(a) __reset__() shouldn't be part of the iterator protocol since it's
not applicable for all iterators, only some.
(b) You can just write a generator and put the setup code before the
initial "yield" to much the same effect.

Maven & would-be designer of languages

More information about the Python-ideas mailing list