I'm learning python online on my own, and I was reading about iterators when this question came out.
Are all iterators objects of one unique class in python, where this class has all the lists, sets, tuple methods?
I'm learning python online on my own, and I was reading about iterators when this question came out.
Are all iterators objects of one unique class in python, where this class has all the lists, sets, tuple methods?
Iterator is not a type. It's a protocol that different types can implement in their own way. A type is an iterator if it defines a method named __next__
that either returns some value or raises StopIteration
when called. The iterator protocol is used by passing an instance of an iterator type to next
, which does nothing but invoke its argument's __next__
method.
# Python equivalent to the builtin:
_next_sentinal = object()
def next(obj, default=_next_sentinal):
try:
return obj.__next__()
except StopIteration:
if default is not _next_sentinal:
return default
raise
An iterable is another part of the iterator protocol: a class that implements a method named __iter__
that returns a value of some type that implements __next__
. The implementation of __iter__
does not have to return the same object that calls the method, or even a value of the same type as the object. (See @kaya's answer for some examples.)
The most common use of the iterator protocol is by a for
loop. The code
for x in foo:
...
uses foo.__iter__
to get an iterator for foo
, then repeatedly calls the foo
iterator's __next__
method to get values to assign to x
.
No, iterators are not all instances of the same class (except in the trivial sense that they are all instances of the base class object
). You can verify this using the type
function on many different iterators; most standard container types and other iterable types built into the language have their own iterator classes.
>>> iterables = [list(), tuple(), set(), frozenset(), dict(), dict().values(), str(), range(1)]
>>> for c in iterables:
... print(type(c), 'has iterator type', type(iter(c)))
...
<class 'list'> has iterator type <class 'list_iterator'>
<class 'tuple'> has iterator type <class 'tuple_iterator'>
<class 'set'> has iterator type <class 'set_iterator'>
<class 'frozenset'> has iterator type <class 'set_iterator'>
<class 'dict'> has iterator type <class 'dict_keyiterator'>
<class 'dict_values'> has iterator type <class 'dict_valueiterator'>
<class 'str'> has iterator type <class 'str_iterator'>
<class 'range'> has iterator type <class 'range_iterator'>
This works because all of the different iterator classes implement the iterator protocol, and Python uses duck typing which means Python code generally doesn't check that objects are instances of the "correct" class, instead it just uses those objects in a certain way and it works as long as those objects have the right attributes and methods to be used in that way (i.e. if they waddle like a duck and quack like a duck...).