I am reading about Python's dunder methods. One of the things I learned is that if a class provides an implementation for __getitem__ and __len__, it can be used in a for loop.
Looking at the built-in classes like list, tuple, and range I noticed that all of them provide an implementation for __iter__ which returns an iterator for a corresponding type. My understanding is that for loop uses this iterator to traverse the elements.
However, how does it work for a class which provides __getitem__ and __len__ but not an __iter__?
As an example, here's a Range class which mimics the in-built range:
class Range(): def __init__(self, start, stop=None, step=1): if step == 0: raise ValueError('step cannot be 0') if stop is None: start, stop = 0, start self._length = max(0, (stop - start + step - 1) // step) self._start = start self._step = step def __len__(self): return self._length def __getitem__(self, k): if k < 0: k = len(self) + k if not 0 <= k < self._length: raise IndexError('Index out of range') return self._start + (k * self._step) Iterating over it with a for loop:
In [21]: for elem in Range(5): ...: print(elem) ...: 0 1 2 3 4