__iter__ methods should always should return an Iterator of some kind,
not an Iterable.
In Python, an Iterable is an object that has an __iter__ method; an
Iterator is an object that has __iter__ and __next__ methods. All
__iter__ methods are expected to return Iterators. Type checkers may
not always recognize an object as being iterable if its __iter__ method
does not return an Iterator.
Every Iterator is an Iterable, but not every Iterable is an Iterator.
For example, list is an Iterable, but not an Iterator; you can obtain
an iterator over a list's elements by passing the list to iter():
>>> importcollections.abc>>> x=[42]>>> isinstance(x,collections.abc.Iterable)True>>> isinstance(x,collections.abc.Iterator)False>>> next(x)Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: 'list' object is not an iterator>>> y=iter(x)>>> isinstance(y,collections.abc.Iterable)True>>> isinstance(y,collections.abc.Iterator)True>>> next(y)42
Using Iterable rather than Iterator as a return type for an __iter__
methods would imply that you would not necessarily be able to call next()
on the returned object, violating the expectations of the interface.