Intermediate·18 min·0/47 done

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.
Certificate