Navigation

Python

How to Create Custom Iterators and Iterables

Transform your custom objects into first-class citizens of Python's iteration ecosystem - make them loop-friendly and memory-efficient.

Table Of Contents

Making Your Objects Loop-Ready

Want your custom objects to work in for loops, list comprehensions, and with all of Python's iteration tools? You need to speak Python's iteration protocol fluently.

Building Your Own Iterators

# Basic iterator class
class Counter:
    def __init__(self, start, end):
        self.current = start
        self.end = end
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.current < self.end:
            num = self.current
            self.current += 1
            return num
        raise StopIteration

# Iterable that returns a new iterator
class Squares:
    def __init__(self, max_value):
        self.max_value = max_value
    
    def __iter__(self):
        # Return a new iterator instance
        return SquareIterator(self.max_value)

class SquareIterator:
    def __init__(self, max_value):
        self.max_value = max_value
        self.num = 0
    
    def __next__(self):
        if self.num < self.max_value:
            result = self.num ** 2
            self.num += 1
            return result
        raise StopIteration

# Generator-based approach (simpler)
class Fibonacci:
    def __init__(self, max_count):
        self.max_count = max_count
    
    def __iter__(self):
        a, b = 0, 1
        for _ in range(self.max_count):
            yield a
            a, b = b, a + b

# Usage
for num in Counter(1, 5):
    print(num)  # 1, 2, 3, 4

squares = Squares(4)
print(list(squares))  # [0, 1, 4, 9]

for fib in Fibonacci(7):
    print(fib, end=" ")  # 0 1 1 2 3 5 8

The Iterator Protocol Decoded

Iterator: Must have __next__() method that:

  • Returns the next value
  • Raises StopIteration when exhausted

Iterable: Must have __iter__() method that:

  • Returns an iterator (could be self)
  • Enables use in for loops and comprehensions

Choose Your Approach

  1. Combined Iterator/Iterable: Simple but single-use (like file objects)
  2. Separate Iterator: More complex but reusable (can iterate multiple times)
  3. Generator-based: Cleanest code with yield - let Python handle the protocol

Real-World Applications

  • Infinite sequences (number generators)
  • Data streaming from large files
  • Custom data structures (trees, graphs)
  • Lazy evaluation patterns

Master Python's Protocols

Dive deeper into Python generators, explore Python's iterator tools, and understand Python's data model for more protocol magic.

Share this article

Add Comment

No comments yet. Be the first to comment!

More from Python