enumerate and zip — the loops ai writes when it's not lazy
zip walks two lists in lockstep — and silently drops the leftovers
Half of "loop over the data" turns into "loop over parallel data."
You have names and scores in separate lists. Headers and values.
Inputs and expected outputs. A request and its response. Anytime you
need to walk two collections side-by-side, AI reaches for zip.
It's exactly the right tool for the job. It also has a single sharp edge that has bitten every Python programmer who has ever used it.
The mental model: tuples paired by position
zip(a, b)
# yields (a[0], b[0]), (a[1], b[1]), (a[2], b[2]), ...
zip produces tuples by lining up the items in each input by
position — like a zipper closing two sides of a jacket. The first
items pair, the second items pair, and so on.
The for x, y in zip(...) syntax then unpacks each tuple into two
named variables, just like enumerate did. Read the line as:
"for each (city, zone) pair when you walk these two lists side by
side…"
The trap: zip stops at the shorter list
Look at the editor:
cities = ["austin", "berlin", "tokyo"] # 3 items
zones = ["CST", "CET"] # 2 items
for city, zone in zip(cities, zones):
print(city, zone)
You'd expect three iterations. You get two:
austin CST
berlin CET
tokyo is silently dropped. There's no warning, no error, no
indication anywhere in the output that an item was missed. zip
reaches the end of the shorter list and stops, full stop.
This is the single most predictable bug in zip-using code. If your
two lists are guaranteed the same length, you're fine. If they're
not — if they came from different parts of an API response, or one
got filtered upstream — zip swallows whatever doesn't fit.
When AI reaches for zip
Phrases in your prompt that trigger zip in Cursor's mind:
- "…match each X with its Y"
- "…pair these two lists together"
- "…walk these in lockstep"
- "…iterate over both at once"
You'll see zip(headers, row), zip(question, answer), zip(inputs, expected), and so on. All the same shape.
Where AI specifically gets zip wrong
Three patterns to flag in code Cursor writes you:
-
No length check before
zip. AI assumes the two lists are the same length and silently truncates. Defense: when reading code that zips data of unknown size, ask whether the function should crash on mismatched lengths, fill in defaults for missing items, or truncate. Each is a valid choice; AI usually picks "truncate" because it's the default behavior ofzip, not because it's what you wanted. -
Three-list
zipgetting truncated by a stale list.zip(names, scores, comments)— ifcommentsis shorter than the other two because it was missing from one record, you lose pairs fromnamesandscoresthat you wanted to keep. The bug looks like missing data with no obvious cause. -
Reaching for
zipwhenenumerateis the right tool. AI sometimes writeszip(range(len(items)), items)when it just wanted indexing. That'senumerate(items)written the long way. Skim for it.
The fix when you need to keep all items
When silently dropping isn't OK, use itertools.zip_longest:
from itertools import zip_longest
for city, zone in zip_longest(cities, zones, fillvalue="UNKNOWN"):
print(city, zone)
zip_longest keeps going until the longest list is exhausted, and
fills in your fillvalue for whichever side ran out. That gives you
all three iterations, with tokyo UNKNOWN on the third.
Run the editor. Two iterations. Notice that tokyo never prints —
that's the silent truncation in action.