How to Create an Iterable Class with __iter__ and __next__ in Python
Build custom iterable classes in Python by implementing the __iter__ and __next__ dunder methods to yield items on demand.
Python code
37 linesclass EvenNumbers:
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
result = self.current
self.current += 2
return result
class FibonacciSequence:
def __init__(self, count):
self.count = count
self.index = 0
self.a, self.b = 0, 1
def __iter__(self):
return self
def __next__(self):
if self.index >= self.count:
raise StopIteration
result = self.a
self.a, self.b = self.b, self.a + self.b
self.index += 1
return result
if __name__ == "__main__":
print("Even numbers up to 10:", list(EvenNumbers(10)))
print("First 8 Fibonacci numbers:", list(FibonacciSequence(8)))
Output
Even numbers up to 10: [0, 2, 4, 6, 8]
First 8 Fibonacci numbers: [0, 1, 1, 2, 3, 5, 8, 13]
How it works
The __iter__ method returns the iterator object itself, which is required for an object to be iterable. The __next__ method returns the next value each time it is called, updating internal state (like self.current or self.a, self.b). When the sequence is exhausted, __next__ raises StopIteration, which signals Python's iteration protocol to stop. The list() constructor and for loops rely on this protocol. This pattern works for any custom sequence where you need to generate values lazily without precomputing them.
Common mistakes
- Forgetting to return `self` from `__iter__`
- Not raising `StopIteration` when the sequence is exhausted
- Mutating shared state incorrectly when multiple iterators are needed
Variations
- Use a generator function with `yield` inside the `__iter__` method for simpler infinite/sequential logic.
- Implement `__getitem__` and `__len__` instead to make the class a sequence.
Real-world use cases
- Paginating through a large API response lazily without loading all pages into memory.
- Walking a file system to yield files that match a pattern while saving memory.
- Generating a custom sequence for a simulation (e.g., pseudo-random numbers or timestamps).
Sponsored
More from OOP & classes
- Add property getter setter validation in Python easy
- Binary Tree Inorder Traversal in Python easy
- Borg pattern shared state in Python medium
- Bridge Pattern in Python: Separate Abstraction from Implementation medium
- Composable Predicates with the &, |, ~ Operators in Python medium
- Composition over Inheritance: How to Build a Wallet Account in Python easy
Keep learning
Related tutorials and quizzes for this topic.