python icon

The Iterator Protocol

Expert Answer & Key Takeaways

Mastering The Iterator Protocol is essential for high-fidelity technical performance and advanced exam competency in 2026.

The Iterator Protocol: iter, next and Custom Iterables (2026)

The Iterator Protocol is the fundamental mechanism that allows any Python object to be used in a for loop or comprehension by implementing the __iter__ and __next__ dunder methods.

1. The Proof Code (Custom Range Implementation)

from typing import Self class CustomRange: """A custom iterable that replicates the basic behavior of range().""" def __init__(self, start: int, end: int): self.start = start self.end = end def __iter__(self) -> Self: # Returns the iterator object (self) self.current = self.start return self def __next__(self) -> int: # Logic to produce the next value if self.current >= self.end: raise StopIteration val = self.current self.current += 1 return val if __name__ == "__main__": nums = CustomRange(1, 4) for n in nums: print(n) # Output: # 1 # 2 # 3

2. Execution Breakdown

  1. The Iterable Interface: An 'Iterable' is an object that implements __iter__. When you start a for loop, Python calls iter(obj), which triggers obj.__iter__().
  2. The Iterator Interface: An 'Iterator' is an object that implements __next__. On every loop iteration, Python calls next(it), which triggers it.__next__().
  3. StopIteration: This exception is the signal that the iteration is complete. It is the only way Python knows when to stop a loop without a fixed size.
  4. State Management: The iterator itself must maintain the state of where it is in the collection. Once an iterator is exhausted, it cannot be 'reset' unless a new iterator is created via __iter__.

3. Detailed Theory

Understanding the separation between an Iterable and its Iterator is key to building complex data structures.

Iterable vs. Iterator

  • Iterable: The collection itself (e.g., a List, String, or our CustomRange class). It 'produces' iterators.
  • Iterator: The stateful object that knows which element is next. In many custom classes, __iter__ simply returns self, making the object both an iterable and its own iterator.

The C-Level 'for' Loop

Internally, a Python for loop is equivalent to this while loop:
_it = iter(iterable) while True: try: item = next(_it) # ... loop body ... except StopIteration: break

Infinite Iterators

Because iterators only produce values on demand, they can represent infinite sequences. The itertools.count() function is a classic example of an infinite iterator that uses the protocol without a predefined end point.
[!TIP] Senior Secret: If you are building a custom collection, keep the 'Iterator' separate from the 'Iterable' if you want to support multiple simultaneous iterations. If __iter__ returns self, you can only iterate over the object once at a time. If it returns a new Iterator object, you can have multiple for loops running on the same collection independently.

Top Interview Questions

?Interview Question

Q:What is the difference between __iter__ and __next__?
A:
__iter__ returns the iterator object itself and is called at the start of a loop. __next__ returns the next value in the sequence and is called on every iteration. It must raise StopIteration when finished.

?Interview Question

Q:How does a 'for' loop know when to stop iterating?
A:
A for loop stops when the iterator's __next__ method raises the StopIteration exception.

?Interview Question

Q:Why can't you iterate over a list twice if its iterator is exhausted?
A:
You can iterate over a list as many times as you want because every for loop creates a new iterator. However, if you manually use an iterator (it = iter(lst)), once it raises StopIteration, it is exhausted and cannot be reused.

Course4All Engineering Team

Verified Expert

Data Science & Backend Engineers

The Python curriculum is designed by backend specialists and data engineers to cover everything from basic logic to advanced automation and API design.

Pattern: 2026 Ready
Updated: Weekly