Python Iterators
How for-loops work, why iterators are single-use, and how zip and enumerate pair values.
Why it matters: DataLoaders, streaming APIs, and file readers are iterators. A spent generator looks like an empty dataset.
Basics
iter and next
An iterable can make an iterator (__iter__). Lists and strings are iterables.
An iterator gives values one at a time with next(). When done, it raises StopIteration.
for x in items: is shorthand for that loop.
Common mistake: looping a generator twice and wondering why the second pass is empty.
Tiny example
Walk a list with iter and next by hand.
it = iter(["a", "b"])
print(next(it))
print(next(it))Basics
zip and enumerate
zip(a, b) pairs items by position. It stops at the shortest input.
Use strict=True (Python 3.10+) to raise if lengths differ.
enumerate(seq, start=1) gives index and value together.
Tiny example
Pair names with scores using zip.
names = ["rag", "mlops"]
scores = [0.9, 0.8]
print(list(zip(names, scores)))Basics
Write a Generator
A generator function with yield is an iterator for free.
Prefer generators over custom iterator classes unless you need extra methods.
itertools adds helpers like islice, chain, and product.
Tiny example
Yield a short countdown.
def countdown(n):
while n > 0:
yield n
n -= 1
print(list(countdown(3)))Then AI / ML
AI / ML examples
Same idea, used in real AI work. Press Try in lab to run it.
AI / ML example
AI / ML: iterators are single-use
The second pass over the generator is empty.
In AI / ML: A second epoch over a spent loader looks like empty data.
example.py
Python
def batches(n):
for i in range(n):
yield f"batch-{i}"
gen = batches(3)
print("first:", list(gen))
print("second:", list(gen))
print("again:", list(batches(3)))AI / ML example 2
AI / ML: pair predictions with labels
strict=True catches length mismatches.
In AI / ML: Eval code must not drop leftover predictions without warning.
example.py
Python
preds = ["pos", "neg", "pos"]
labels = ["pos", "pos"]
try:
print(list(zip(preds, labels, strict=True)))
except ValueError as err:
print("mismatch:", err)
print("safe slice:", list(zip(preds[:2], labels)))Takeaways
- 1for-loops call iter() then next() until StopIteration.
- 2Generators and zip objects are consumed once.
- 3Use zip(..., strict=True) when lengths must match.