1. The Iterator Protocol (__iter__ & __next__)
StopIteration Exception Mechanics
- An iterable is an object with an `__iter__()` method that returns an iterator.
- An iterator is an object with a `__next__()` method that returns the next value.
- When no elements remain, `__next__()` raises the `StopIteration` exception, which Python for loops catch automatically.
numbers = [10, 20]
it = iter(numbers)
print(next(it)) # 10
print(next(it)) # 20
# next(it) -> Raises StopIteration!