Когда нужно пройтись по списку (или другому итерируемому объекту) и при этом получить номер каждого элемента, начинающие разработчики на Python иногда делают счетчик вручную в отдельной переменной или используют range (len(…)).
Но в Python есть более простой и короткий способ — функция enumerate(), которая позволяет получать пары (индекс, значение) быстрее, проще и с меньшим количеством ошибок.
Синтаксис enumerate()
Чаще всего enumerate() используют в циклах. Функция enumerate() принимает итерируемый объект (то, по чему можно пройтись в цикле for) и возвращает итератор, который на каждом шаге цикла for отдает кортеж из двух элементов: (index, value).
Кортеж можно как распаковать на отдельные индекс и значение, так и оставить в исходном виде. Про распаковку расскажем ниже.
Какие объекты можно передавать в enumerate()
Для передачи в функцию enumerate(iterable) в качестве iterable подойдут любые итерируемые объекты, например:
- списки (list) и кортежи (tuple),
- строки (str),
- последовательность (range),
- генераторы,
- множества (set),
- словари (dict) и их представления: keys(), values(), items().
Простой пример с enumerate(iterable)
Передаем в enumerate() объект items.
for i, x in enumerate(items): print(i, value)
По умолчанию индексация начинается с нуля, то есть первый элемент получит индекс 0, второй 1 и так далее. Получим что-то вроде:
0 item1 1 item2
Изменение нумерации с параметром start
Если нужно начать нумерацию не с нуля, а с другого числа, используйте параметр start:
for i, x in enumerate(items, start=1): print(i, value)
Здесь нумерация начнется с индекса 1. Тогда вывод будет примерно таким:
1 item1 2 item2
Функция enumerate() вне цикла
Вне for функция enumerate() встречается реже, но иногда ее используют как обычный источник пар (индекс, значение), например:
- Чтобы быстро получить первый пронумерованный элемент через next().
first_pair = next(enumerate(items))
Вывод: (0, первый_элемент)
- Чтобы преобразовать результат в список или словарь.
Список list():
pairs = list(enumerate(items))
Вывод: [(0, …), (1, …), …]
Словарь dict():
index_map = dict(enumerate(items))
Вывод: {0: …, 1: …, …}
Как работает enumerate() внутри цикла for
for i, x in enumerate() и распаковка
Когда вы пишете
items = ["a", "b", "c"] for i, x in enumerate(items): print(i, x)
происходит распаковка итерируемого объекта:
- i получает индекс (0, 1, 2…). Индекс — это всегда int.
- x получает соответствующий элемент списка. Он может быть любого типа.
Например, для items = [«a», «b», «c»] цикл пройдет так:
0 a 1 b 2 c

for pair in enumerate()
Вариант с for pair in enumerate(items) — это тот же самый перебор, только без распаковки. На каждом шаге цикла вы получаете всю пару целиком в одной переменной pair.
Пример:
items = ["a", "b", "c"] for pair in enumerate(items): print(pair)
Вывод:
(0, 'a') (1, 'b') (2, 'c')
Чем enumerate() лучше range(len(…))

Читаемость и меньше ошибок с индексами
С range(len(…)) вы работаете с индексом отдельно и каждый раз обращаетесь к элементу через items[i], например:
for i in range(len(items)): print(i, items[i])
С enumerate() индекс и элемент приходят сразу:
for i, x in enumerate(items): print(i, x)
Это делает код чище и спасает от возможных ошибок с индексами, именами списка и т. д. Также enumerate() работает с любыми итерируемыми объектами без len(), а это удобно.
Когда range(len(…)) оправдан
Вариант с range(len(…)) удобен, когда нужен обход по индексу с особым шагом или направлением. Например:
- Нужен шаг больше 1 (каждый второй, каждый третий элемент):
for i in range(0, len(items), 2): print(i, items[i])
- Нужен обратный обход по индексам:
for i in range(len(items) - 1, -1, -1): print(i, items[i])
- Нужно обращаться к элементам с соседними индексами (i и i+1), например в сравнениях:
for i in range(len(items) - 1): if items[i] > items[i + 1]: <действие при выполнении условия>
В «обычных» же сценариях, когда вы хотите вытащить элемент и его индекс из коллекции, enumerate() выглядит удобнее.
Сценарии enumerate() со списками list
Хотя enumerate() работает с любыми итерируемыми объектами, чаще всего его применяют именно со списками.
Список — это изменяемая структура, в которой нужны и индекс, и сам элемент. Например, чтобы обновить значение по позиции, показать нумерацию пользователю или быстро найти нужный элемент.
Найти индекс по условию
Например, нужно найти позицию первого элемента, который подойдет под условие.
Пример:
Условие — элемент должен быть больше 8.
items = [3, 7, 10, 2] found_index = None for i, x in enumerate(items): if x > 8: found_index = i break print(found_index)
Вывод: 2 (т. к. при нумерации от 0 элемент со значением 10 имеет индекс 2).
Если бы элемент не был найден, то found_index остался бы None.
Обновить элементы по индексу
Списки можно изменять по индексу.
Пример:
Каждый из элементов списка будет увеличен в 2 раза.
items = [1, 2, 3] for i, x in enumerate(items): items[i] = x * 2 print(items)
Вывод: [2, 4, 6]
Важно: если вы меняете список прямо в цикле, то лучше менять только значения по текущему индексу и не удалять элементы из этого же списка во время итераций. Удаление и вставка меняют длину списка и сдвигают индексы. Это может привести к непредсказуемым результатам.
Другие итерируемые объекты
В enumerate() можно передавать строки, кортежи, множества. Отличаться будет только элемент при итерациях и то, можно ли менять исходный объект по индексу.
Строки (str)
Элемент, по которому «пробегается» цикл — символ. Строки неизменяемые, так что можно только вывести элементы либо создать новую строку с нужными правками.
for i, ch in enumerate("Python"):
print(i, ch)
Вывод:
0 P 1 y
Кортежи (tuple)
Работает так же, как и список, но кортеж неизменяемый, т. е. обновить элемент по индексу нельзя.
t = ("a", "b", "c")
for i, x in enumerate(t):
print(i, x)
Вывод:
0 a 1 b
Множества (set)
У множеств нет фиксированного порядка. Индексы, которые выдает enumerate(), будут просто «номерами шага», а не настоящими позициями.
s = {"a", "b", "c"}
for i, x in enumerate(s):
print(i, x)
Пример:
0 b 1 a 2 c
В выводе результата не получится гарантировать порядок, так как он может отличаться при каждом запуске.
Словари (dict)
Если передать словарь напрямую, enumerate() будет перебирать ключи:
d = {"a": 10, "b": 20}
for i, key in enumerate(d):
print(i, key)
Вывод:
0 a 1 b
Если нужны значения, используйте .values():
for i, value in enumerate(d.values()): print(i, value)
Вывод:
0 10 1 20
Если нужны пары ключ-значение, используйте .items() и распакуйте их:
for i, (key, value) in enumerate(d.items()): print(i, key, value)
Вывод:
0 a 10 1 b 20
Здесь i — это номер шага, а (key, value) — это текущая пара из словаря.
Генераторы
Генераторы выдают элементы по одному и не хранят их все в памяти.
gen = (x * 2 for x in range(3)) for i, x in enumerate(gen): print(i, x)
Вывод:
0 0 1 2 2 4
Комбинации enumerate с zip и другие связки
Функцию enumerate() используют не только для простого перебора списка, но и в связках, когда нужно нумеровать более сложные конструкции. Например, параллельный обход нескольких последовательностей, вложенные циклы, таблицы и матрицы.
Нумерация параллельного перебора
Если нужно пройтись по двум спискам одновременно и при этом иметь номер строки, удобно комбинировать zip() и enumerate().
names = ["Иван", "Алина", "Олег"] scores = [10, 7, 12] for i, (name, score) in enumerate(zip(names, scores), start=1): print(i, name, score)
Вывод:
1 Иван 10 2 Алина 7 3 Олег 12
Функция zip(names, scores) дает пары (name, score), а enumerate(…, start=1) добавляет к ним номер, начиная с 1.
Вложенные циклы и «индексы индексов»
Во вложенных структурах (например, список списков) часто нужны два индекса: индекс строки и индекс элемента внутри строки.
matrix = [ [1, 2, 3], [4, 5, 6], ] for row_i, row in enumerate(matrix): for col_i, value in enumerate(row): print(row_i, col_i, value)
Вывод:
0 0 1 0 1 2 0 2 3 1 0 4 1 1 5 1 2 6
Коротко об enumerate()
- enumerate() помогает перебирать список и одновременно получать индекс каждого элемента без ручного счетчика и без range(len(…)).
- Функция принимает любой итерируемый объект и возвращает итератор, который на каждом шаге отдает кортеж (index, value).
- По умолчанию индексация начинается с 0, а через параметр start можно задать стартовую нумерацию, например с 1.
- В цикле удобнее распаковывать пару сразу через for i, x in enumerate(items) либо получать кортеж целиком с помощью for pair in enumerate(items).
- По сравнению с range(len(…)) enumerate() читается проще и снижает шанс ошибок с индексами. Но иногда range(len(…)) оправдан: когда нужны шаг, обратный обход или работа с соседними индексами.
- Со списками enumerate() особенно полезен, потому что список можно менять по индексу.
- При изменении списка в цикле безопаснее менять значения по текущему индексу и не удалять элементы во время обхода, иначе сдвигаются индексы и результат становится непредсказуемым.
- enumerate() работает и с другими типами: со строками, кортежами, множествами, словарями и т. д.
- enumerate() хорошо сочетается с генераторами, со связками вроде zip() (параллельный перебор) и вложенными циклами (индексы строк и столбцов).
