How to Implement the Iterator Protocol in Python
A manual iterator class using __iter__ and __next__, compared with an equivalent generator using yield.
Python code
27 linesclass ManualCounter:
def __init__(self, limit):
self.limit = limit
self.current = 0
def __iter__(self):
return self
def __next__(self):
if self.current >= self.limit:
raise StopIteration
value = self.current
self.current += 1
return value
def generator_counter(limit):
for i in range(limit):
yield i
if __name__ == "__main__":
manual = ManualCounter(5)
print("Manual iterator:", list(manual))
gen = generator_counter(5)
print("Generator:", list(gen))
Output
Manual iterator: [0, 1, 2, 3, 4]
Generator: [0, 1, 2, 3, 4]
How it works
The ManualCounter class follows the iterator protocol by defining __iter__ (returning itself) and __next__ (returning the next value or raising StopIteration when done). list(manual) repeatedly calls __next__ until the exception is raised. The generator_counter function uses yield instead — each call to next() resumes execution right after the last yield. Both produce identical sequences, but the generator version is shorter and handles state automatically. range() is already an iterable, so iterating over it in the generator keeps memory constant regardless of limit.
Common mistakes
- Forgetting to implement __iter__ when defining a custom iterator class
- Mutating the iterable while iterating over it
- Raising StopIteration from inside a generator instead of using return
- Assuming an iterator is reusable — list(manual) can only be consumed once
Variations
- Use iter() and next() builtins explicitly to step through a manual iterator
- Convert a manual iterator to an iterator of tuples with zip(*[iter(obj)]*n) for batching
Real-world use cases
- Building a custom streaming reader that yields database rows one at a time.
- Implementing an infinite or stateful sequence, such as a pseudo-random number generator.
- Creating a lazy wrapper around an expensive paginated API response.
Sponsored
More from Comprehensions & generators
- Batch Rows in Chunks with a Generator in Python easy
- Build a Generator Pipeline in Python: Filter Then Map medium
- Build a lazy generator to read file lines in Python easy
- Chunk an Iterable into Batches with a Generator in Python easy
- Convert Data in Python with Comprehensions and Generators easy
- Count Data in Python with Comprehensions and Generators easy
Keep learning
Related tutorials and quizzes for this topic.