Iterator: Separate Traversal from Storage
A caller wants values in order without knowing whether storage is an array or linked list. Iterator provides traversal without exposing the underlying representation.
Python’s iter and next
class Shelf:
def __init__(self, books):
self.books = list(books)
def __iter__(self):
return iter(self.books)
shelf = Shelf(["one", "two"])
iterator = iter(shelf)
print(next(iterator))
print(list(iterator))
print(list(shelf))
The outputs are one, then ['two'], then ['one', 'two']. The iterator remembers its position. After consuming one value, only the remaining value appears. Shelf creates a fresh iterator each time, allowing another traversal from the beginning.
Python’s for loop uses this protocol. A generator with yield can calculate values as needed instead of creating a full list first. That does not remove storage already occupied by the original data.
Be careful when modifying during traversal
Adding or removing elements while iterating can behave differently across structures and implementations. Consider iterating over a snapshot or collecting edits to apply afterward.
Check your understanding
After consuming an iterator completely, does looping over the same iterator restart it?
Show explanation
A typical iterator remains exhausted. Create a new iterator from a reusable source to restart. Sources such as files or network streams may have additional restrictions.