enumerate() and zip()¶
Both functions wrap an existing iterable and yield tuples. enumerate() pairs each element with its index; zip() pairs elements from two or more iterables.
enumerate()¶
enumerate() adds an index counter to any iterable. It is the idiomatic replacement for range(len(sequence)):
fruits = ["apple", "banana", "cherry"]
# Avoid this
for i in range(len(fruits)):
print(i, fruits[i])
# Prefer this
for i, fruit in enumerate(fruits):
print(i, fruit)
Output:
0 apple
1 banana
2 cherry
The default counter starts at 0. Use start= to begin at a different value:
tasks = ["Buy groceries", "Call mom", "Finish homework"]
for i, task in enumerate(tasks, start=1):
print(f"{i}. {task}")
Output:
1. Buy groceries
2. Call mom
3. Finish homework
zip()¶
zip() combines elements from multiple iterables into tuples, stopping at the shortest:
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
for name, age in zip(names, ages):
print(name, age)
Output:
Alice 25
Bob 30
Charlie 35
Three iterables at once:
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
cities = ["NYC", "LA", "Chicago"]
for name, age, city in zip(names, ages, cities):
print(f"{name} is {age} and lives in {city}")
Output:
Alice is 25 and lives in NYC
Bob is 30 and lives in LA
Charlie is 35 and lives in Chicago
Converting zip output¶
zip() is lazy — wrap it in list() to materialise the pairs:
pairs = list(zip(names, ages))
print(pairs) # [('Alice', 25), ('Bob', 30), ('Charlie', 35)]
Building a dictionary from two lists¶
keys = ["name", "age", "city"]
values = ["Alice", 25, "NYC"]
person = dict(zip(keys, values))
print(person) # {'name': 'Alice', 'age': 25, 'city': 'NYC'}
Unzipping¶
The * operator unpacks a list of pairs back into separate sequences:
pairs = [("Alice", 25), ("Bob", 30), ("Charlie", 35)]
names, ages = zip(*pairs)
print(names) # ('Alice', 'Bob', 'Charlie')
print(ages) # (25, 30, 35)
Key Ideas¶
enumerate() is the idiomatic way to iterate with an index — prefer it over range(len(seq)).
zip() is the idiomatic way to iterate over two or more sequences in parallel — prefer it over indexing both manually.
Both functions are lazy: they produce one tuple at a time without building the full result in memory.