Iterator Pattern¶
Category: Behavioral Pattern
Overview¶
Provide a way to access elements of an aggregate object sequentially without exposing its underlying representation. This pattern decouples the traversal logic from the collection, allowing different traversal algorithms while keeping the collection interface simple.
Usage Guidelines¶
Use when:
- Need to access collection elements sequentially
- Want different ways to traverse same collection
- Want uniform interface for traversing different collections
- Internal collection structure should be hidden
Avoid when:
- Built-in iteration is sufficient for simple collections
- Need random access to elements
- Only one way to traverse collection exists
- Python's built-in iteration protocol works well
Implementation¶
from __future__ import annotations
from typing import Iterator as TypingIterator
class Book:
"""Represents a book in the library."""
def __init__(self, title: str, author: str) -> None:
"""Initialize a book."""
self.title = title
self.author = author
def __str__(self) -> str:
"""String representation of the book."""
return f"{self.title} by {self.author}"
class BookIterator:
"""Concrete iterator for books."""
def __init__(self, books: list[Book]) -> None:
"""Initialize the iterator."""
self._books = books
self._index = 0
def has_next(self) -> bool:
"""Check if more books exist."""
return self._index < len(self._books)
def next(self) -> Book:
"""Get next book."""
if not self.has_next():
raise StopIteration("No more books")
book = self._books[self._index]
self._index += 1
return book
class BookCollection:
"""Concrete aggregate of books implementing Python iterator protocol."""
def __init__(self) -> None:
"""Initialize an empty book collection."""
self._books: list[Book] = []
def add_book(self, book: Book) -> None:
"""Add a book to the collection."""
self._books.append(book)
def create_iterator(self) -> BookIterator:
"""Create an iterator for this collection."""
return BookIterator(self._books)
def __iter__(self) -> TypingIterator[Book]:
"""Make collection iterable using Python's iterator protocol."""
return iter(self._books)
def __len__(self) -> int:
"""Get collection length."""
return len(self._books)
Usage¶
# Book collection with Python's iterator protocol
library = BookCollection()
library.add_book(Book("Design Patterns", "Gang of Four"))
library.add_book(Book("Clean Code", "Robert Martin"))
library.add_book(Book("Refactoring", "Martin Fowler"))
# Using Python's for loop
for book in library:
print(book)
# Output:
# Design Patterns by Gang of Four
# Clean Code by Robert Martin
# Refactoring by Martin Fowler
# Using custom iterator
iterator = library.create_iterator()
while iterator.has_next():
book = iterator.next()
print(book.title)
Trade-offs¶
Benefits:
- Separates traversal logic from collection (Single Responsibility Principle)
- Multiple traversals can happen simultaneously
- Same interface for different collections provides uniformity
- Collection internals remain hidden through encapsulation
Drawbacks:
- Overkill for simple collections
- Additional abstraction adds performance overhead
- Iterator must track traversal state
- Modifying collection during iteration can cause problems
Real-World Examples¶
- Database result sets iterating through query results
- File systems traversing directories and files
- DOM traversal walking through HTML/XML trees
- Graph traversal with BFS, DFS algorithms
Related Patterns¶
- Composite
- Factory Method
- Memento
- Visitor
API Reference¶
design_patterns.behavioral.iterator
¶
Iterator Pattern Module
The Iterator pattern provides a way to access elements of an aggregate object sequentially without exposing its underlying representation. It decouples the traversal logic from the collection, allowing different traversal algorithms.
Example
Iterating through a custom collection:
Aggregate
¶
BinaryTree
¶
Binary tree with custom iterator.
Source code in src/design_patterns/behavioral/iterator.py
__init__()
¶
create_iterator()
¶
insert(value)
¶
Insert a value into the tree.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
int
|
Value to insert. |
required |
Book
¶
Represents a book in the library.
Source code in src/design_patterns/behavioral/iterator.py
__init__(title, author)
¶
Initialize a book.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
title
|
str
|
Book title. |
required |
author
|
str
|
Book author. |
required |
BookCollection
¶
Bases: Aggregate
Concrete aggregate of books implementing Python iterator protocol.
Source code in src/design_patterns/behavioral/iterator.py
__init__()
¶
__iter__()
¶
Make collection iterable using Python's iterator protocol.
Returns:
| Type | Description |
|---|---|
Iterator[Book]
|
Iterator over books. |
__len__()
¶
add_book(book)
¶
Add a book to the collection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
book
|
Book
|
Book to add. |
required |
create_iterator()
¶
get_book(index)
¶
Get book at index.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index
|
int
|
Book index. |
required |
Returns:
| Type | Description |
|---|---|
Book
|
Book at the specified index. |
BookIterator
¶
Bases: Iterator
Concrete iterator for books.
Source code in src/design_patterns/behavioral/iterator.py
__init__(books)
¶
Initialize the iterator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
books
|
list[Book]
|
List of books to iterate. |
required |
has_next()
¶
Check if more books exist.
Returns:
| Type | Description |
|---|---|
bool
|
True if more books exist. |
InOrderIterator
¶
Bases: Iterator
Iterator for in-order tree traversal.
Source code in src/design_patterns/behavioral/iterator.py
__init__(root)
¶
Initialize in-order iterator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
TreeNode | None
|
Root of the tree. |
required |
has_next()
¶
next()
¶
Get next node value in in-order traversal.
Returns:
| Type | Description |
|---|---|
int
|
Next node value. |
Raises:
| Type | Description |
|---|---|
StopIteration
|
When no more nodes exist. |
Source code in src/design_patterns/behavioral/iterator.py
Iterator
¶
Bases: ABC
Abstract iterator interface.
Source code in src/design_patterns/behavioral/iterator.py
Range
¶
Custom range implementation demonstrating iterator pattern.
Source code in src/design_patterns/behavioral/iterator.py
__init__(start, end, step=1)
¶
Initialize range.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
int
|
Start value. |
required |
end
|
int
|
End value (exclusive). |
required |
step
|
int
|
Step size. |
1
|
Source code in src/design_patterns/behavioral/iterator.py
__iter__()
¶
Create iterator for the range.
Returns:
| Type | Description |
|---|---|
Iterator[int]
|
Range iterator. |
__len__()
¶
Calculate range length.
Returns:
| Type | Description |
|---|---|
int
|
Number of elements in range. |