Jim Jim - 4 months ago 14
Python Question

Iterators for built-in containers

From my understanding so far, you can easily create an iterator for a user-defined object by simply defining both the

__iter__
method and the
__next__
method for it. That's pretty intuitive to understand.

I also get it that you can manually build an iterator for any built-in container by simply calling the
iter()
method on that container.

Using basically any container as an example, what I don't understand is why they don't define a
__next__
method for themselves. Instead, when calling the
iter
method on a container (ergo,
<container>.__iter__
) it returns a new object of type
<container_type>_iterator
and not the container itself.




So finally, the question is, why do container objects delegate their
iterator
functionality to separate
<type>_iterator
objects instead of defining it themselves?

Answer

If the container was its own iterator (e.g. provided a __next__ method), you could only iterate over it in one place. You could not have independent iterators. Each call to __next__ would give the next value in the container and you'd not be able to go back to the first value; you have in effect a generator that could only ever yield the values in the container just the once.

By creating separate iterators for a given container, you can iterate independently:

>>> lst = ['foo', 'bar', 'baz']
>>> it1 = iter(lst)
>>> it2 = iter(lst)
>>> next(it1)
'foo'
>>> next(it2)
'foo'
>>> list(it1)
['bar', 'baz']
>>> next(it2)
'bar'