How do I loop over two lists at once in Python?
Short answer
Use zip to pair the items from two sequences and loop over the pairs. Note that zip stops at the shorter one, silently ignoring extra items, so pass strict=True to catch a length mismatch.
The short version
Use zip to walk two (or more) sequences together, pairing their items. Be aware that zip stops at the shortest one and silently discards the extras. On Python 3.10 and later, pass strict=True so a length mismatch raises instead of being ignored.
Pairing two sequences
names = ["pen", "mug", "cup"]
prices = [2, 5, 4]
for name, price in zip(names, prices):
print(name, price)
Each iteration yields a tuple, which the two names on the left unpack. It is far clearer than indexing both lists with a shared counter.
The pattern it replaces
for i in range(len(names)):
print(names[i], prices[i]) # clumsy, and breaks if the lists differ in length
This is harder to read and assumes the lists are the same length without checking.
The silent truncation trap
list(zip([1, 2, 3], ["a"])) # [(1, 'a')] , items 2 and 3 vanish
zip stops when the shortest sequence runs out, with no warning. If the two lists were supposed to correspond one to one, a mismatch means your data is wrong, and silently dropping the extras hides that.
The fix: strict=True
list(zip([1, 2, 3], ["a"], strict=True))
# ValueError: zip() argument 2 is shorter than argument 1
This turns a silent data loss into a clear error. Use it whenever the sequences are meant to be the same length, which is nearly always. It was added in Python 3.10.
Zipping more than two
zip takes any number of sequences.
for name, price, stock in zip(names, prices, stocks, strict=True):
...
Building a dictionary
A very common use is pairing keys with values.
dict(zip(names, prices)) # {'pen': 2, 'mug': 5, 'cup': 4}
Unzipping
The star operator reverses it, splitting a list of pairs back into separate sequences.
pairs = [("pen", 2), ("mug", 5)]
names, prices = zip(*pairs)
With an index too
Combine with enumerate when you need the position as well.
for i, (name, price) in enumerate(zip(names, prices, strict=True), start=1):
print(i, name, price)
Note the brackets around (name, price), which unpack the inner tuple that zip produced.