An iterator is an object that supplies successive values, usually one at a time. Python's iterator protocol connects objects to for loops through __iter__, __next__, and StopIteration. Strings, lists, tuples, dictionaries, files, and custom objects can participate; integers cannot. section 10.0
A for loop effectively performs these steps:
- Call iter(object) to obtain an iterator. section 10.0
- Call next(iterator) repeatedly to request values. section 10.0
- Stop when the iterator raises StopIteration. section 10.0
A stateful iterator class
class MyIterator: def __init__(self, data): self.data = data self.index = 0 def __iter__(self): return self def __next__(self): if self.index >= len(self.data): raise StopIteration value = self.data[self.index] self.index += 1 return value for value in MyIterator('abc'): print(value) The object stores its position because __next__ loses local state between calls. Returning self from __iter__ is convenient, but it makes the iterator consumable: a second loop sees the exhausted position. section 10.2
When an object should support multiple independent loops, separate the iterable from a helper iterator. The iterable's __iter__ can return a fresh helper, avoiding shared index state. Other valid implementations return self, a helper instance, or a generator. section 10.2 section 10.7
Generator functions and generator expressions provide shorter ways to create iterators. They preserve execution state at yield points and can calculate values lazily, reducing memory use compared with constructing a list, especially when processing large files. section 10.26 section 7.17
class LoudIterator():
def __init__(self, data):
print('\tNow in __init__')
self.data = data #1
self.index = 0 #2
def __iter__(self):
print('\tNow in __iter__')
return self #3
def __next__(self):
print('\tNow in __next__')
if self.index >= len(self.data): #4
print(
f'\tself.index ({self.index}) is too big; exiting')
raise StopIteration
value = self.data[self.index] #5
self.index += 1 #6
print('\tGot value {value}, incremented index to {self.index}')
return value
for one_item in LoudIterator('abc'):
print(one_item)
Trace construction, iterator acquisition, each __next__ call, index updates, returned values, and final StopIteration. section 10.0














