Python › Iterators & the Iterator Protocol

How do you implement a custom iterator by defining __iter__ and __next__?

Intermediate

Answer

A custom iterator class defines __next__() to return the next value or raise StopIteration when exhausted, and __iter__() to return self so the object works directly in for-loops and with the built-in iter() function.
class Countdown:
    def __init__(self, start):
        self.current = start
    def __iter__(self):
        return self
    def __next__(self):
        if self.current <= 0:
            raise StopIteration
        self.current -= 1
        return self.current + 1

for n in Countdown(3):
    print(n)  # 3 2 1
Real-world example A custom paginated API client implements __next__ to fetch and yield the next page of results lazily as the caller iterates.

Common follow-ups: Why must __iter__ return self on an iterator?;How does this differ from a generator-based approach?