Creating an Iterator in Python

3 min read ·

Creating an iterator means defining a custom object that can be traversed one element at a time.
Such an object must follow the iterator protocol so that Python can iterate over it using a for loop or the next() function.
Custom iterators are useful when built in data structures are not sufficient for a specific iteration logic.

Rules for Creating an Iterator

To create an iterator, a class must implement two special methods.
__iter__() __next__()
If either method is missing, the object will not behave as an iterator.

Step One Defining the Iterator Class

A custom iterator is always created using a class.
This class will be responsible for managing the iteration state.

Step Two Implementing iter()

The __iter__() method must return the iterator object itself.
This method is called when iteration starts.
Returning self tells Python that the object itself is the iterator.

Step Three Implementing next()

The __next__() method defines how the next value is produced.
It must return the next element in the sequence.
When no values remain, it must raise StopIteration.
This iterator generates numbers starting from one up to a fixed limit.

Using the Custom Iterator

Once created, the iterator can be used with a for loop.
Output 1 2 3
Python automatically handles the StopIteration exception.

Using next() Manually

Iterators can also be consumed manually using next().
Calling next() again raises StopIteration.

How Iteration State Is Maintained

The iterator stores its current position using instance variables.
In the example, self.current keeps track of progress.
Each call to __next__() updates this state.
This is why iterators remember where they left off.

Iterator Exhaustion

Once an iterator raises StopIteration, it becomes exhausted.
It cannot be reused.
The second loop produces no output.
To iterate again, a new iterator object must be created.

Common Mistakes When Creating Iterators

Forgetting to raise StopIteration Returning a value instead of raising StopIteration Not returning self from __iter__()
These mistakes cause infinite loops or runtime errors.

When to Create Custom Iterators

Custom iterators are useful when Iteration logic is complex Data is generated dynamically Large datasets must be processed lazily
They give full control over how values are produced.

Comparison with Generators

Custom iterators require more code.
Generators provide the same behavior using yield.
Iterators are preferred when Complex state management is required Object oriented design is needed
Understanding custom iterators is essential before mastering generators.