Функция enumerate() в Python: как получить индекс и элемент в цикле for

Функция enumerate() в Python перебирает список и на каждом шаге отдаёт номер элемента и сам элемент, так что ручной счётчик и range(len()) больше не нужны.

Разбираем синтаксис и start=1, работу со строками, словарями, zip и файлами, а в конце шесть частых ошибок: от забытой распаковки до удаления элементов прямо в цикле.

Статью написал:
Ваня Буявец, продюсер, основатель Checkroi
Ваня Буявец
Основатель Checkroi, продюсер, эксперт в выборе онлайн-курсов
Все 3067 статей автора Подписаться на Телеграм-канал
Одобрено экспертом:
Наташа Буявец, основатель Checkroi, эксперт по онлайн-курсам
Наташа Буявец
Основательница Checkroi, продюсер Youtube-каналов, эксперт по онлайн-курсам
Все 3721 экспертное мнение Подписаться на Телеграм-канал
Обложка: Функция enumerate() в Python: как получить индекс и элемент в цикле for

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

Заводить счётчик вручную и писать range(len(spisok)) не придётся. enumerate работает со всем, что перебирается в цикле for: списками, строками, кортежами, словарями, строками файла. Если вы только начинаете, сначала посмотрите основные команды Python, там разобраны списки и цикл for.

CheckroiCheckroiПодборка курсов по Python569 курсов • 51 школаСравните цены, школы, программу и найдите выгодные предложения по обучениюСравнить→

Что делает 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: пошаговая инструкция

Возьмём обычную задачу: вывести список покупок с номерами.

  1. Подготовьте коллекцию. Например, fruits = ["яблоко", "банан", "вишня"].
  2. Оберните её в enumerate внутри цикла. Вместо for fruit in fruits: пишем for i, fruit in enumerate(fruits):.
  3. Распакуйте пару в две переменные. Первая получает номер, вторая получает элемент. Порядок именно такой.
  4. Работайте с обеими переменными в теле цикла.
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 взяты по привычке. Интерпретатору всё равно, как вы назовёте переменные, лишь бы их было две.

Канал основателя Checkroi Вани Буявца3 700 человек читают мой Телеграм-канал про нейросетиСобрал промпты для Claude Code и ChatGPT, разборы ИИ-инструментов и лайфхаки по продвижению бизнеса в одном местеПрисоединиться

Чем 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-разработчик»
Перейти на сайт курса
SkillboxSkillbox157 335 ₽5987 ₽/мес.10 месяцевОбзор курса
Fullstack-разработчик на Python
Перейти на сайт курса
НетологияНетология137 000 ₽7125 ₽/мес.21 месяцОбзор курса
ДО Профессия Python-разработчик
Перейти на сайт курса
GeekBrainsGeekBrains149 001 ₽3167 ₽/мес.10 месяцевОбзор курса
Автоматизированное тестирование на Python
Перейти на сайт курса
SkillboxSkillbox122 226 ₽4108 ₽/мес.9 месяцевОбзор курса
Профессия Python-разработчик
Перейти на сайт курса
SkillFactorySkillFactory154 044 ₽4279 ₽/мес.10 месяцевОбзор курса

Больше программ — в полном каталоге курсов по Python

Часто задаваемые вопросы

Что такое enumerate в Python простыми словами?

Это встроенная функция, которая на каждом шаге цикла for отдаёт номер элемента и сам элемент. Запись for i, item in enumerate(spisok): заменяет ручной счётчик и range(len(spisok)).

Как сделать, чтобы enumerate считал с единицы?

Передайте второй аргумент: enumerate(spisok, start=1) или короче enumerate(spisok, 1). Меняется только счётчик, индексы самого списка по-прежнему идут с нуля.

Чем enumerate отличается от range(len())?

range(len()) даёт только индекс, элемент приходится доставать отдельно через spisok[i]. enumerate отдаёт сразу пару «номер, элемент» и работает с файлами и генераторами, у которых нет длины.

Как использовать enumerate со словарём?

enumerate(slovar) перебирает только ключи. Чтобы получить номер, ключ и значение, передайте items(): for i, (key, value) in enumerate(slovar.items()):.

Почему второй list(enumerate(...)) вернул пустой список?

enumerate возвращает итератор, и его пары расходуются за один проход. Вызывайте enumerate() заново для каждого цикла или сохраните пары списком: pairs = list(enumerate(spisok)).

Что возвращает enumerate, если его напечатать?

print(enumerate(spisok)) покажет строку вида <enumerate object at 0x...>, а не пары. Чтобы увидеть содержимое, оберните объект в list().

Читайте Checkroi первым в Google
Добавьте Checkroi в избранные источники — и наши разборы курсов и обзоры школ будут показываться выше в вашей выдаче Google.
Оставить комментарий
0 комментариев
Форма комментария

Оставьте комментарий

Напишите, что думаете. Нам важно ваше мнение!