Ошибка IndexError: list index out of range и как её исправить

Ошибки Pythonобновлено 07.10.202610 мин чтенияесть тренажёр

IndexError в Python — это ошибка обращения к элементу, которого нет: в списке 4 элемента, а программа просит пятый. Обычно виноваты счёт с единицы вместо нуля, цикл, который проходит на шаг дальше длины, или пустой список. Исправление — сверить индекс с len().

Загружаем…

Что означает IndexError в Python

IndexError в Python — это сигнал «такого номера здесь нет». Интерпретатор нашёл список, строку или кортеж, но номер в квадратных скобках выходит за их границы.

Представьте полку с четырьмя книгами, пронумерованными 0, 1, 2 и 3. Просьба «дай книгу номер 4» не имеет смысла: такой книги на полке просто нет. Python поступает честно — не придумывает значение, а останавливает программу и сообщает, что индекс вне диапазона. Попробуйте запустить код в редакторе выше: программа выведет четыре оценки и на пятом шаге упадёт. Под выводом появится сообщение и подсказка на русском.

ocenki = [5, 4, 5, 3]
print(ocenki[4])
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    print(ocenki[4])
IndexError: list index out of range

Последняя строка сообщения самая важная: именно там написано слово IndexError. Слово перед двоеточием — тип ошибки, после двоеточия — пояснение. «list index out of range» переводится как «индекс списка вне диапазона». Для строки будет «string index out of range», для кортежа — «tuple index out of range». Все эти варианты описаны в разделе о встроенных исключениях официальной документации Python[1].

Индексы начинаются с нуля

Первый элемент списка в Python имеет индекс 0, а последний — индекс len(spisok) - 1. Это правило объясняет большинство ошибок выхода за границы.

Нумерация с нуля закреплена в официальной документации Python, в разделе о последовательностях. В жизни мы считаем с единицы: первый урок, второй подъезд, третий этаж. В Python нумерация элементов начинается с нуля, и новичку легко ошибиться на единицу. Если в списке 5 элементов, допустимые индексы — 0, 1, 2, 3 и 4. Номера 5 уже нет, хотя длина списка равна пяти. Запрос пятого номера и есть выход за границы списка.

Элемент"кот""пёс""ёж""сова"
Индекс слева0123
Индекс справа-4-3-2-1

У списка zveri = ["кот", "пёс", "ёж", "сова"] длина 4. Индексы 0–3 и −1…−4 работают, а zveri[4] и zveri[-5] вызывают IndexError. Отрицательные номера считают с конца: −1 — последний элемент. Подробнее о том, как устроены списки и их методы, рассказано в уроке про списки в Python.

zveri = ["кот", "пёс", "ёж", "сова"]
print(len(zveri))
print(zveri[0], zveri[3])
print(zveri[-1])
4
кот сова
сова

Пять типичных причин выхода за границы

Выход за границы списка почти всегда сводится к 5 ситуациям. Если узнать свою в таблице, исправление займёт меньше минуты.

ПричинаПример с ошибкойКак исправить
Счёт с единицыa[len(a)]Последний элемент — a[len(a) - 1] или a[-1]
Цикл на шаг длиннееrange(len(a) + 1)range(len(a)) или for x in a
Пустой список или строкаa[0] при a = []Сначала проверить if a:
Сосед справаa[i + 1] в цикле по всем iЦикл до len(a) - 1
Присваивание в новую ячейкуa[3] = 7 при длине 3a.append(7)

Последняя строка таблицы удивляет многих. Список в Python не растягивается сам, когда вы пишете в несуществующую ячейку: сообщение будет «list assignment index out of range». Новый элемент добавляют методом append(), а не присваиванием по номеру. Запомните: IndexError бывает и при чтении, и при записи.

Пример: цикл, который заходит слишком далеко

Цикл с range(len(a) + 1) — это самый частый источник ошибки в школьных задачах. Последний шаг такого цикла просит элемент, которого не существует.

Функция range(4) выдаёт числа 0, 1, 2, 3 — правая граница не входит. Поэтому range(len(a)) уже перебирает все допустимые номера, и прибавлять единицу не нужно. Ошибка рождается из желания «захватить последний элемент»: кажется, что без + 1 он потеряется. Описание функции range() в документации Python прямо говорит, что конечное значение в последовательность не входит. Эта граница — главный виновник того, что IndexError появляется в учебных задачах. Проверить легко: выведите list(range(len(a))) и сравните с таблицей индексов.

temp = [12, 15, 9]
for i in range(len(temp) + 1):
    print(temp[i])

Программа выведет 12, 15, 9, а на четвёртом шаге, когда i станет равно 3, остановится. Есть два способа исправить. Первый — убрать + 1. Второй, ещё надёжнее, — перебирать сами элементы, а не их номера: тогда индексы вообще не появляются в коде и ошибиться в них невозможно. Больше примеров перебора — в уроке о цикле for и range.

temp = [12, 15, 9]
for t in temp:
    print(t)

for i, t in enumerate(temp):
    print("День", i + 1, ":", t)

Функция enumerate() выдаёт пары «номер и значение» и тоже никогда не выходит за границы. Её удобно использовать, когда номер нужен для вывода. PEP 8 и официальное руководство Python Software Foundation показывают именно такой стиль перебора.

Сравнение с соседом

В задачах вида «найдите, сколько раз число выросло» сравнивают a[i] и a[i + 1]. На последнем шаге соседа справа нет, поэтому цикл должен остановиться на один шаг раньше. Иначе выход за границы случится на самой последней итерации.

a = [3, 5, 4, 8, 10]
rost = 0
for i in range(len(a) - 1):
    if a[i + 1] > a[i]:
        rost += 1
print(rost)

Пустой список и короткая строка

Если список пуст, любой индекс вызывает ошибку, даже 0 и −1. То же со строками: у пустой строки нет ни первого, ни последнего символа.

Пустой список появляется незаметно: пользователь нажал Enter, ничего не введя, фильтр не нашёл ни одного подходящего числа, или все элементы удалили методом pop(). Код, который отлично работал на тестовом примере, падает на пустом вводе. Тест только на удобных данных такую ошибку не выявит. Поэтому перед обращением к a[0] стоит спросить себя: «А может ли здесь быть пусто?» Если может, нужна проверка.

slovo = input("Введите слово: ")
if slovo:
    print("Первая буква:", slovo[0])
    print("Последняя буква:", slovo[-1])
else:
    print("Вы ничего не ввели")

Условие if slovo: истинно только для непустой строки, а if spisok: — только для непустого списка. Это короче, чем len(slovo) > 0, и так рекомендует руководство PEP 8[2]. С методом pop() история та же: у пустого списка он тоже остановит программу с текстом «pop from empty list». Как устроены индексы символов, подробно показано в статье про строки и срезы.

«Срез тоже вызовет ошибку, если выйти за границы». Это миф: срез a[2:100] при короткой строке просто вернёт то, что есть, или пустую строку. Такая ошибка возникает только при обращении к одному элементу по номеру.

s = "кот"
print(s[1:100])
print(s[5:10] == "")

Как исправить IndexError в Python за 4 шага

Чтобы исправить IndexError в Python, выясните, какой индекс программа просила и какая длина была у списка в этот момент. Разница между ними подскажет причину.

  1. Найти строку. В сообщении указан номер строки. Посмотрите, какие квадратные скобки в ней есть — ошибка в одной из них.
  2. Вывести индекс и длину. Прямо перед этой строкой добавьте print(i, len(a)). Если i равно длине или больше, граница цикла неверна.
  3. Проверить пустоту. Если длина 0, ищите, почему список не заполнился: ввод, условие фильтра, удаление элементов.
  4. Упростить перебор. Где возможно, замените for i in range(len(a)) на for x in a: номера исчезнут вместе с риском ошибки.

Отладочный print() не стоит оставлять в готовой программе: после исправления удалите его. Подробнее о поиске ошибок через вывод промежуточных значений рассказано в материале об отладке программ. В школьном курсе одномерные массивы по федеральной образовательной программе изучают в 9 классе[3], и на этих задачах подобная ошибка встречается чаще всего.

«Достаточно обернуть код в try/except, и ошибка исчезнет». Это не подтверждается практикой: try/except прячет сообщение, но неправильная граница цикла остаётся, и программа выдаст неверный ответ без всякого предупреждения.

Когда проверка длины не поможет

Проверка len() не поможет, если ошибка в логике, а не в одной границе. В этих 4 случаях нужно менять сам алгоритм.

  • Список меняется прямо в цикле. Если удалять элементы во время перебора range(len(a)), длина уменьшается, а цикл идёт до старой границы — индекс выскочит за край уже на 1-м удалении. Собирайте результат в новый список.
  • Двумерная таблица и 2 индекса. В pole[y][x] легко перепутать строку и столбец: длина проверена для одного измерения, а ошибка в другом.
  • Ввод через split дал меньше 3 чисел. Код ждёт chasti[2], а пользователь ввёл два числа. Проверка нужна у входных данных, а не у цикла.
  • Номер приходит от пользователя. Человек вводит «5», думая о пятом элементе, а программа берёт индекс 5 — шестой. Вычтите 1 и проверьте, что номер не больше длины.

Чего делать нельзя

Нельзя исправлять такую ошибку случайными правками чисел: «уберу единичку, вдруг заработает». Так легко потерять последний элемент и не заметить этого.

  • Нельзя писать range(len(a) + 1) «для надёжности» — это не надёжность, а гарантированный выход за край.
  • Не следует обращаться к a[0] без проверки, если список пришёл из ввода или фильтра.
  • Не стоит удалять элементы из списка внутри цикла по его индексам: длина меняется на ходу.
  • Не допускается заполнять пустой список присваиванием a[i] = ... — используйте append().
  • Не стоит глушить ошибку пустым except, не разобравшись в причине.
  • Нельзя путать номер для человека и индекс для Python: пятый по счёту элемент имеет индекс 4.

Если в похожей ситуации вы работаете со словарём и получаете другое сообщение, загляните в разбор ошибки KeyError со словарями: там вместо номера ищут ключ. Общий порядок чтения любых сообщений интерпретатора описан в статье как читать ошибки Python.

Источники

[1] The Python Tutorial (официальная документация Python 3). Python Software Foundation. — синтаксис и встроенные функции.

[2] van Rossum G., Warsaw B., Coghlan N. PEP 8 — Style Guide for Python Code. Python Software Foundation, 2001.

[3] Приказ Минпросвещения России от 18.05.2023 № 370 «Об утверждении федеральной образовательной программы основного общего образования». — информатика 7–9 (см. факты).

Вопросы и ответы

Почему индексы в Python начинаются с нуля?

Индекс показывает, на сколько шагов нужно отойти от начала. Первый элемент стоит в самом начале, шагов ноль. Так устроено в большинстве языков программирования, не только в Python.

Как получить последний элемент без риска?

Используйте a[-1]: он всегда указывает на последний элемент, какой бы длины ни был список. Но если список пуст, ошибка будет и здесь, поэтому сначала проверьте if a:.

Чем IndexError в Python отличается от KeyError?

Первая ошибка — про номер в списке, строке или кортеже. Вторая — про отсутствующий ключ в словаре. Причина похожа: просим то, чего нет, но лечение разное.

Бывает ли эта ошибка в Scratch?

В Scratch элементы списка нумеруются с 1, а запрос несуществующего номера возвращает пустое значение без остановки программы. Поэтому дети, пришедшие из Scratch, часто впервые встречают эту ошибку именно в Python.

Может ли индекс быть дробным?

Нет. Индекс должен быть целым числом. Запись a[1.0] вызовет уже TypeError. Если номер получился делением, используйте целочисленное деление //. Обычное деление для индекса не подходит, даже если результат выглядит целым.

Встречается ли такая ошибка на ОГЭ?

В задании 16 ОГЭ программу пишут на универсальном языке, и при работе с массивами обращение к несуществующему элементу — частая причина неверного ответа. Структура экзамена описана в материалах ФИПИ. Перед сдачей проверяйте программу на пустом и на самом коротком вводе.