Python · Iterators
The iterator protocol behind every for loop: iter(), next(), StopIteration, and writing an iterator class.
What for x in obj: really does:
it = iter(obj)asks the iterable for an iterator (obj.__iter__()).- It calls
next(it)again and again (it.__next__()). - It stops when
StopIterationis raised.
An iterable (list, string, dict, file) can hand out fresh iterators. An iterator remembers where it is and is used up after one pass. That explains why looping over the same zip or map object a second time gives nothing.
To write your own iterator, give the class __iter__ (which returns self) and __next__.
nums = [10, 20, 30]
it = iter(nums)
print(next(it), next(it), next(it))
try:
next(it)
except StopIteration:
print("StopIteration")
class Countdown:
def __init__(self, start):
self.n = start
def __iter__(self):
return self
def __next__(self):
if self.n <= 0:
raise StopIteration
self.n -= 1
return self.n + 1
print(list(Countdown(5)))
z = zip("abc", [1, 2, 3])
print(list(z))
print(list(z)) # exhausted iterator
Output:
10 20 30
StopIteration
[5, 4, 3, 2, 1]
[('a', 1), ('b', 2), ('c', 3)]
[]Sources
- Iterators (tutorial) — Python Software Foundation
- Iterator types — Python Software Foundation
- Glossary: iterable — Python Software Foundation