Функция enumerate() в Python перебирает список и на каждом шаге отдаёт сразу две вещи: номер элемента и сам элемент. Пишется так: for i, item in enumerate(spisok):. Нумерация по умолчанию идёт с нуля, а если нужна с единицы, добавьте второй аргумент: enumerate(spisok, start=1).
Заводить счётчик вручную и писать range(len(spisok)) не придётся. enumerate работает со всем, что перебирается в цикле for: списками, строками, кортежами, словарями, строками файла. Если вы только начинаете, сначала посмотрите основные команды Python, там разобраны списки и цикл for.
Что делает enumerate в Python

По документации Python, enumerate возвращает объект-итератор. Каждый его шаг выдаёт кортеж из двух значений: счётчик и очередной элемент исходной коллекции. Синтаксис:
enumerate(iterable, start=0)| Параметр | Что передать | По умолчанию |
|---|---|---|
iterable |
Список, строку, кортеж, словарь, файл, любой объект, который перебирается в цикле | обязательный |
start |
Число, с которого начнётся счётчик | 0 |
Сам по себе enumerate ничего не печатает и список не создаёт. Это ленивый объект: пары появляются по одной, когда их просит цикл, next() или list().
fruits = ["яблоко", "банан", "вишня"]
e = enumerate(fruits)
print(e)
print(next(e))
print(list(e))
print(list(enumerate(fruits, 10)))
Вывод:
<enumerate object at 0x1076d8d60>
(0, 'яблоко')
[(1, 'банан'), (2, 'вишня')]
[(10, 'яблоко'), (11, 'банан'), (12, 'вишня')]
Адрес в первой строке у вас будет другим. Важнее третья строка: после next(e) первая пара уже израсходована, и list(e) вернул только оставшиеся две. К этому вернёмся в разделе про ошибки.
Как пользоваться enumerate: пошаговая инструкция
Возьмём обычную задачу: вывести список покупок с номерами.
- Подготовьте коллекцию. Например,
fruits = ["яблоко", "банан", "вишня"]. - Оберните её в enumerate внутри цикла. Вместо
for fruit in fruits:пишемfor i, fruit in enumerate(fruits):. - Распакуйте пару в две переменные. Первая получает номер, вторая получает элемент. Порядок именно такой.
- Работайте с обеими переменными в теле цикла.
fruits = ["яблоко", "банан", "вишня"]
for i, fruit in enumerate(fruits):
print(i, fruit)
Вывод:
0 яблоко
1 банан
2 вишня
Для человека список с нуля выглядит странно, поэтому для вывода на экран почти всегда ставят start=1. Заодно соберём строку через f-строку:
fruits = ["яблоко", "банан", "вишня"]
for n, fruit in enumerate(fruits, start=1):
print(f"{n}. {fruit}")
Вывод:
1. яблоко
2. банан
3. вишня
Имена i, n, idx взяты по привычке. Интерпретатору всё равно, как вы назовёте переменные, лишь бы их было две.
Чем enumerate лучше счётчика и range(len())

Без enumerate номер элемента получают двумя способами. Оба работают, но в обоих легко ошибиться.
fruits = ["яблоко", "банан", "вишня"]
i = 0
for fruit in fruits:
print(i, fruit)
i += 1
for i in range(len(fruits)):
print(i, fruits[i])
Оба цикла печатают то же самое, что и enumerate. В первом случае счётчик живёт отдельно от цикла: забыли i += 1 или поставили его после continue, и номера поехали. Во втором вы получаете индекс, а элемент достаёте отдельно через fruits[i], и строка становится длиннее. Ручной счётчик привычен по циклу while, там без него не обойтись, подробности в статье про while.
| Способ | Что получаете | Где подводит |
|---|---|---|
Ручной счётчик i += 1 |
номер и элемент | лишние две строки, счётчик легко забыть или сдвинуть |
range(len(x)) |
только индекс | не работает с файлом и генератором: у них нет len() |
enumerate(x) |
номер и элемент | пары расходуются за один проход |
В официальном учебнике сначала показывают range(len(a)), а следом говорят, что в большинстве таких случаев удобнее enumerate. Функцию добавили в язык в версии 2.3 именно для этого приёма, причины описаны в PEP 279.
Примеры enumerate на практике
Изменить элементы списка по индексу
Если перебирать список обычным for, присвоить новое значение элементу не выйдет: у вас есть значение, но нет его места в списке. enumerate даёт индекс, и правка становится одной строкой. Сделаем скидку 10 % на всё, что дороже 200:
prices = [100, 250, 80, 400]
for i, price in enumerate(prices):
if price > 200:
prices[i] = price * 0.9
print(prices)
[100, 225.0, 80, 360.0]
Умножение на дробь превратило целые числа в float, поэтому 225.0, а не 225. Так можно только менять значения на месте. Чтобы добавить новые элементы, нужны append() и insert().
Перебрать строку
Строка тоже последовательность, enumerate проходит её по символам:
for i, letter in enumerate("код"):
print(i, letter)
0 к
1 о
2 д
Больше приёмов со строками собрано в шпаргалке по методам строк.
Пронумеровать словарь
Если передать в enumerate сам словарь, он пойдёт по ключам. Чтобы получить ключ и значение вместе, передайте items() и распакуйте пару в скобках:
ages = {"Анна": 25, "Борис": 31}
for i, name in enumerate(ages):
print(i, name)
for i, (name, age) in enumerate(ages.items(), start=1):
print(i, name, age)
0 Анна
1 Борис
1 Анна 25
2 Борис 31
Собрать словарь из списка
Пары из enumerate можно сразу отдать в dict(). Если нужен обратный словарь «значение → номер», поможет генератор словаря:
cities = ["Москва", "Казань", "Пермь"]
print(dict(enumerate(cities, start=1)))
print({city: i for i, city in enumerate(cities)})
{1: 'Москва', 2: 'Казань', 3: 'Пермь'}
{'Москва': 0, 'Казань': 1, 'Пермь': 2}
Найти все индексы нужного значения
Метод index() возвращает только первое вхождение. Все позиции собирает генератор списка с enumerate:
marks = [5, 3, 5, 4, 5]
print([i for i, m in enumerate(marks) if m == 5])
[0, 2, 4]
Нумеровать два списка сразу через zip
Когда имена и баллы лежат в разных списках, их склеивает zip(), а enumerate добавляет место в рейтинге. Внутренняя пара снова распаковывается в скобках:
names = ["Анна", "Борис", "Вера"]
scores = [91, 78, 85]
for place, (name, score) in enumerate(zip(names, scores), start=1):
print(place, name, score)
1 Анна 91
2 Борис 78
3 Вера 85
Показать номер строки в файле
Файл в Python перебирается построчно, и enumerate с start=1 даёт номер строки ровно как в редакторе. Удобно, когда надо сообщить, где в данных ошибка. Пусть есть файл data.csv, в котором у второй записи нет имени:
id;name
1;Анна
2;
3;Вера
with open("data.csv", encoding="utf-8") as f:
for line_no, line in enumerate(f, start=1):
if line.rstrip("\n").endswith(";"):
print(f"Строка {line_no}: пустое поле")
Строка 3: пустое поле
Здесь range(len()) не сработал бы вообще, у файла нет длины. Как открывать файлы и почему через with, разобрано в инструкции по open(), а про сам формат есть статья о CSV.
Обойти таблицу из вложенных списков
Два вложенных enumerate дают номер строки и номер столбца:
rows = [["Имя", "Балл"], ["Анна", 91], ["Борис", 78]]
for r, row in enumerate(rows):
for c, cell in enumerate(row):
print(f"[{r}][{c}] = {cell}")
[0][0] = Имя
[0][1] = Балл
[1][0] = Анна
[1][1] = 91
[2][0] = Борис
[2][1] = 78
Взять каждый второй элемент
С индексом под рукой легко отобрать элементы по позиции через остаток от деления:
for i, fruit in enumerate(["яблоко", "банан", "вишня", "груша", "слива"]):
if i % 2 == 0:
print(fruit)
яблоко
вишня
слива
Если нужен только сам список без обработки, короче будет срез spisok[::2]. Как он устроен, рассказано в статье о срезах.
Частые ошибки с enumerate и что с ними делать

Шесть ситуаций, на которых чаще всего ломается код с enumerate.
Забыли распаковать пару
Симптом: вместо номера и слова печатаются кортежи вида (0, 'яблоко'). Причина: в цикле одна переменная, и в неё попадает вся пара целиком.
Решение: две переменные через запятую, for i, fruit in enumerate(fruits):.
Перепутали порядок переменных
Первым всегда идёт номер, вторым элемент. Если написать наоборот, Python не выдаст ошибку, просто имена переменных начнут врать:
fruits = ["яблоко", "банан", "вишня"]
for fruit, i in enumerate(fruits):
print(i, fruit)
яблоко 0
банан 1
вишня 2
Решение: запомнить порядок «номер, потом значение» и проверять его по первому выводу цикла.
Второй проход вернул пустоту
enumerate возвращает итератор, и пары в нём расходуются за один проход. Если сохранить объект в переменную и перебрать его второй раз, получится пустой список:
fruits = ["яблоко", "банан", "вишня"]
pairs = enumerate(fruits)
print(list(pairs))
print(list(pairs))
[(0, 'яблоко'), (1, 'банан'), (2, 'вишня')]
[]
Решение: вызывать enumerate(fruits) заново в каждом цикле или один раз сохранить пары списком, pairs = list(enumerate(fruits)).
Обратились к enumerate по индексу или через len()
У объекта enumerate нет ни индексов, ни длины:
pairs = enumerate(["яблоко", "банан", "вишня"])
pairs[0] # TypeError: 'enumerate' object is not subscriptable
len(pairs) # TypeError: object of type 'enumerate' has no len()
Решение: то же, что выше, превратить в список через list(). Или взять длину у исходной коллекции.
start=1 сдвинул индексы при правке списка
Параметр start меняет только счётчик, а позиции в списке по-прежнему считаются с нуля. Если писать в список по номеру из start=1, правка уедет на соседний элемент:
prices = [100, 250, 80]
for n, price in enumerate(prices, start=1):
if price == 250:
prices[n] = 0
print(prices)
[100, 250, 0]
Хотели обнулить 250, обнулили 80. Решение: ставьте start=1 только для вывода людям, а для записи по индексу оставляйте счёт с нуля.
Удаляли элементы прямо в цикле
Пытаемся убрать все двойки из [1, 2, 2, 3]:
nums = [1, 2, 2, 3]
for i, x in enumerate(nums):
if x == 2:
nums.pop(i)
print(nums)
[1, 2, 3]
Одна двойка выжила. После удаления элементы сдвинулись влево, а enumerate шагнул дальше и вторую двойку перескочил. В учебнике Python пишут, что в таких случаях обычно проще перебирать копию коллекции или собрать новую.
Решение: новый список через генератор, [x for x in nums if x != 2] даст [1, 3]. Другие способы удаления описаны в статье про удаление элементов из списка.
Где освоить Python системно
enumerate стоит в одном списке встроенных функций с zip(), sorted() и len(). Все они работают без import, и их стоит выучить раньше сторонних библиотек. Закрепить их удобно на задачах: начните с 30 задач для новичков, а функции разберите по инструкции про def.
Если нужна программа с наставником и проверкой домашних заданий, загляните в каталог курсов Python: там программы разных школ можно сравнить по цене и длительности. Вот пять из них:
| Курс | Школа | Стоимость со скидкой | В рассрочку | Длительность | Обзор курса от Checkroi |
|---|---|---|---|---|---|
| Профессия «Python-разработчик» Перейти на сайт курса | 157 335 ₽ | 5987 ₽/мес. | 10 месяцев | Обзор курса | |
| Fullstack-разработчик на Python Перейти на сайт курса | 137 000 ₽ | 7125 ₽/мес. | 21 месяц | Обзор курса | |
| ДО Профессия Python-разработчик Перейти на сайт курса | 149 001 ₽ | 3167 ₽/мес. | 10 месяцев | Обзор курса | |
| Автоматизированное тестирование на Python Перейти на сайт курса | 122 226 ₽ | 4108 ₽/мес. | 9 месяцев | Обзор курса | |
| Профессия Python-разработчик Перейти на сайт курса | 154 044 ₽ | 4279 ₽/мес. | 10 месяцев | Обзор курса |
Больше программ — в полном каталоге курсов по Python




