enumerate и zip в Python: шпаргалка

Карьерник — квиз-тренажёр в Telegram с 1500+ вопросами для собесов аналитика. SQL, Python, A/B, метрики. Бесплатно.

enumerate — индекс + значение

for i, value in enumerate(list):
    print(i, value)

Заменяет антипаттерн for i in range(len(list)).

1. Базовое использование

words = ['apple', 'banana', 'cherry']

for i, word in enumerate(words):
    print(i, word)
# 0 apple
# 1 banana
# 2 cherry

2. Стартовый индекс

for i, word in enumerate(words, start=1):
    print(i, word)
# 1 apple
# 2 banana
# 3 cherry

3. В list comprehension

[(i, w.upper()) for i, w in enumerate(words)]
# [(0, 'APPLE'), (1, 'BANANA'), (2, 'CHERRY')]

# индексы, где условие истинно
[i for i, w in enumerate(words) if len(w) > 5]
# [1, 2]

4. Словарь индексов

word_idx = {w: i for i, w in enumerate(words)}
# {'apple': 0, 'banana': 1, 'cherry': 2}

5. Итерация с шагом

for i, w in enumerate(words):
    if i % 2 == 0:  # только чётные
        print(w)

zip — параллельно по двум спискам

for a, b in zip(list1, list2):
    process(a, b)

6. Базовое использование

names = ['Alice', 'Bob', 'Charlie']
ages = [30, 25, 35]

for name, age in zip(names, ages):
    print(f"{name} is {age}")
# Alice is 30
# Bob is 25
# Charlie is 35

7. Три и более списка

colors = ['red', 'green', 'blue']
fruits = ['apple', 'pear', 'berry']
prices = [100, 50, 200]

for c, f, p in zip(colors, fruits, prices):
    print(c, f, p)

8. zip в dict

names = ['Alice', 'Bob']
ages = [30, 25]

dict(zip(names, ages))
# {'Alice': 30, 'Bob': 25}

9. Транспонирование матрицы

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

transposed = list(zip(*matrix))
# [(1, 4, 7), (2, 5, 8), (3, 6, 9)]

*matrix распаковывает строки как отдельные аргументы zip.

10. Разархивация

pairs = [('Alice', 30), ('Bob', 25), ('Charlie', 35)]

names, ages = zip(*pairs)
# names = ('Alice', 'Bob', 'Charlie')
# ages = (30, 25, 35)

11. zip + enumerate (комбинация)

for i, (name, age) in enumerate(zip(names, ages)):
    print(i, name, age)

12. Разная длина

zip останавливается на самом коротком списке:

a = [1, 2, 3]
b = ['x', 'y']

list(zip(a, b))
# [(1, 'x'), (2, 'y')]  — 3 потеряна

Если хотите заполнить — itertools.zip_longest:

from itertools import zip_longest

list(zip_longest(a, b, fillvalue='-'))
# [(1, 'x'), (2, 'y'), (3, '-')]

Практические примеры

13. Пары соседних элементов

values = [10, 20, 30, 40, 50]

for prev, curr in zip(values, values[1:]):
    diff = curr - prev
    print(f"{prev} → {curr}: diff = {diff}")

14. Ранжирование

scores = [85, 92, 78, 95, 88]
names = ['Alice', 'Bob', 'Charlie', 'David', 'Eve']

# сортировка по score
ranked = sorted(zip(scores, names), reverse=True)
for i, (score, name) in enumerate(ranked, 1):
    print(f"{i}. {name}: {score}")
# 1. David: 95
# 2. Bob: 92
# ...

15. Параллельная обработка DataFrame

import pandas as pd

df = pd.DataFrame({
    'product': ['A', 'B', 'C'],
    'price':   [100, 200, 150],
    'qty':     [3, 2, 4]
})

for product, price, qty in zip(df['product'], df['price'], df['qty']):
    total = price * qty
    print(f"{product}: {total}")

16. Поиск пар с условием

pairs = list(zip(names, ages))
young = [name for name, age in pairs if age < 30]
# ['Bob']

17. Merge двух отсортированных списков

a = [1, 3, 5, 7]
b = [2, 4, 6, 8]

merged = sorted(list(a) + list(b))
# или через zip (не merge, но sometimes useful)

18. Dictionary update с двух списков

keys = ['name', 'age', 'city']
values = ['Alice', 30, 'Moscow']

user = dict(zip(keys, values))
# {'name': 'Alice', 'age': 30, 'city': 'Moscow'}

Антипаттерны

Антипаттерн 1. range(len())

# плохо — не pythonic
for i in range(len(words)):
    print(i, words[i])

# хорошо
for i, w in enumerate(words):
    print(i, w)

Антипаттерн 2. Итерация по индексу без нужды

# плохо
for i in range(len(list1)):
    a = list1[i]
    b = list2[i]
    process(a, b)

# хорошо
for a, b in zip(list1, list2):
    process(a, b)

Антипаттерн 3. Явный счётчик

# плохо
i = 0
for item in items:
    print(i, item)
    i += 1

# хорошо
for i, item in enumerate(items):
    print(i, item)

Частые ошибки

Ошибка 1. zip неравных списков

По умолчанию обрезает до короткого. Используйте zip_longest, если это не то, что нужно.

Ошибка 2. zip создаёт итератор, не список

z = zip(a, b)
list(z)  # [...]
list(z)  # [] — итератор исчерпан!

# правильно — сразу в list
pairs = list(zip(a, b))

Ошибка 3. enumerate на словаре

d = {'a': 1, 'b': 2}
for i, key in enumerate(d):
    print(i, key)   # i=0, key='a', ...

# но чаще нужны key+value
for i, (k, v) in enumerate(d.items()):
    print(i, k, v)

Ошибка 4. Забыть распаковку в for

pairs = [(1, 'a'), (2, 'b')]

# плохо
for pair in pairs:
    num = pair[0]
    letter = pair[1]

# хорошо
for num, letter in pairs:
    ...

Связанные темы

FAQ

enumerate нужен всегда?

Нет, только если нужен индекс. Если индекс не нужен — просто for item in items.

zip медленнее обычного цикла?

Нет, zip быстрее range(len()) подхода, т.к. работает на уровне C.

Можно ли менять список в enumerate?

Можно по индексу: list[i] = new_value. Но лучше собирать новый список через comprehension.

zip для словарей?

dict(zip(keys, values))  # соединение в словарь

Тренируйте Python — откройте тренажёр с 1500+ вопросами для собесов.