Python enumerate для пар индекс и значение

Python enumerate добавляет бегущий индекс к итерируемому объекту и возвращает пары (индекс, значение) при обходе. Используйте его, когда нужна позиция каждого элемента, например для нумерованного вывода или меток. Это встроенный паттерн для связывания элемента с его позицией в списках, генераторах или строках файла.

Пример Python Enumerate Для Нумерованного Вывода

Вывод:

Результат появится здесь...

Вывод:

1. отправить заказ
2. написать клиенту

Как Работает Этот Пример

  1. enumerate(tasks, start=1) связывает каждую задачу с её позицией.
  2. start=1 делает номера человекочитаемыми.
  3. Вывод показывает каждую задачу с номером.

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

Ошибка 1: Забыть, что нумерация начинается с 0.

for line_no, row in enumerate(rows):
    print(f"Строка {line_no}: {row['sku']}")
for line_no, row in enumerate(rows, start=1):
    print(f"Строка {line_no}: {row['sku']}")

Почему это происходит: enumerate по умолчанию стартует с 0, что корректно для индексов, но сбивает в пользовательских номерах строк.

Ошибка 2: Перебирать словарь и ожидать значения.

region_totals = {"запад": 1200, "восток": 980}
for i, total in enumerate(region_totals):
    print(i, total)
region_totals = {"запад": 1200, "восток": 980}
for i, (region, total) in enumerate(region_totals.items(), start=1):
    print(i, region, total)

Почему это происходит: при итерации по dict возвращаются ключи, поэтому enumerate связывает индекс с ключом, если не использовать .items(). Если нужен паттерн ключ/значение, см. пример Python dict.

Ошибка 3: Делать list(enumerate(...)) для больших данных.

indexed_rows = list(enumerate(rows, start=1))
for line_no, row in indexed_rows:
    print(line_no, row)
for line_no, row in enumerate(rows, start=1):
    print(line_no, row)

Почему это происходит: list() загружает все пары в память, тогда как enumerate и так ленивый и может стримить.

enumerate vs range(len()): что использовать

Используйте enumerate, когда…Используйте range(len()), когда…
Нужны и индекс, и элемент вместе.Нужны только числовые индексы.
Вы итерируете любой объект, включая генераторы.Нужно ходить с кастомным шагом или только по индексам.
Хотите читабельные циклы без ручной индексации.Работаете с индексами для срезов или случайного доступа.

Правило: выбирайте enumerate для индекса + значения; range(len()) — когда нужен сам индекс. Если нужны только вычисления с индексами, см. пример Python range.

Соображения По Производительности

enumerate — это O(n) и ленивость, поэтому он не создаёт лишний список пар, если вы не оборачиваете его в list(). На практике он быстрее и понятнее, чем вызов list.index() внутри цикла (что делает цикл O(n^2)). Если вам нужно только пронумеровать строки, enumerate сохраняет постоянную память и даёт номера строк.

Другие случаи использования enumerate

Отмечать строки с ошибками при анализе логов.

lines = [
    "INFO подключено",
    "ОШИБКА таймаут",
    "INFO повтор",
]

for line_no, line in enumerate(lines, start=1):
    if "ОШИБКА" in line:
        print(f"Строка {line_no}: {line}")

Это оставляет точный номер строки рядом с каждой ошибкой, ускоряя отладку и разбор инцидентов. Так же работает и для файлов, потому что enumerate принимает любой итерируемый объект.

Нормализовать список на месте по индексу.

names = ["  ada", "grace ", "  linus"]
for i, name in enumerate(names):
    # обновляем по индексу, когда нужно мутировать список на месте
    names[i] = name.strip().title()

print(names)

Это оставляет данные в том же списке и даёт индекс для обратного присваивания. Так понятнее, чем вести ручной счётчик, и цикл остаётся читаемым.