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.

Easy Python 3.9+ Aug 9, 2026 OOP & classes 14 views 0 copies

Python code

37 lines
Python 3.9+
class 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

stdout
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

  1. Use a generator function with `yield` inside the `__iter__` method for simpler infinite/sequential logic.
  2. 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

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from OOP & classes

Related tutorials and quizzes for this topic.