Interview frequency: …
Short answer
The object must define __iter__ returning an iterator, and the iterator defines __next__ that returns the next item and raises StopIteration at the end (and defines __iter__ returning self).
Explanation
A for loop calls iter() once and then next() repeatedly until StopIteration. The easiest way to implement the protocol is to make __iter__ a generator function. Keep the collection separate from the iteration state: if you store the iteration position inside the object itself, you cannot iterate it twice independently or in a nested way.
Code example
class Countdown:
def __init__(self, start: int):
self.start = start
def __iter__(self): # Each call starts an independent iteration
n = self.start
while n > 0:
yield n
n -= 1
print(list(Countdown(3))) # [3, 2, 1]Common mistakes
- Storing the iteration state in the object itself, so it can be iterated only once.
- Returning None from __iter__ instead of an iterator.