IndexError: list index out of range — что значит и как исправить

опубликовано
читать
≈ 6 мин
автор
среда и версия
Python 3.14 в Pyodide 314.0.3 — исполняемые блоки запускаются прямо на странице
содержание решать задачи Python для начинающих

IndexError: list index out of range переводится как «индекс списка вне диапазона». Код обратился к элементу по номеру, а элемента с таким номером в списке нет. Номера в Python начинаются с нуля, поэтому у списка из четырёх элементов есть индексы 0, 1, 2 и 3, а с конца — от -1 до -4. Всё, что за этими границами, даёт IndexError.

У той же ошибки есть родственные сообщения: string index out of range для строк, tuple index out of range для кортежей, list assignment index out of range при записи и pop from empty list для пустого списка. Причины у них общие — разберём их по очереди. Все примеры можно запустить кнопкой прямо на странице.

Python / 01

Четыре элемента — индексы от 0 до 3

Четыре элемента — индексы от 0 до 3Список cities из четырёх городов: Москва, Казань, Пермь, Сочи. Над элементами индексы с начала: 0, 1, 2, 3; под ними индексы с конца: -4, -3, -2, -1. Пятой ячейки с индексом 4 нет. cities[3] и cities[-1] возвращают Сочи, а cities[4] даёт IndexError: list index out of range.cities = ["Москва", "Казань", "Пермь", "Сочи"]01234МоскваКазаньПермьСочиэлемента нет-4-3-2-1cities[3] → Сочиcities[-1] → Сочиcities[4] → IndexError
Последний индекс всегда на единицу меньше длины: у четырёх элементов это 3. Индекс 4 указывает на ячейку, которой нет, и Python отвечает IndexError.

Как читать сообщение

Трассировка показывает файл, номер строки и само выражение, а знаки ^ под ним отмечают, где именно случился выход за границы:

cities = ["Москва", "Казань", "Пермь", "Сочи"]
print(len(cities))
print(cities[4])
4
Traceback (most recent call last):
  File "main.py", line 3, in <module>
    print(cities[4])
          ~~~~~~^^^
IndexError: list index out of range

Чтобы понять, что пошло не так, достаточно двух чисел: длины списка и индекса, к которому обратился код. Если индекс считается в цикле или приходит из данных, выведи оба через print прямо перед строкой с ошибкой.

Причина 1: счёт с нуля

Самая частая ошибка — взять последний элемент по номеру, равному длине. Последний индекс на единицу меньше: len(cities) - 1. Ещё проще — отрицательный индекс -1, он всегда означает последний элемент. Отрицательные индексы тоже ограничены: у четырёх элементов самый дальний — -4.

cities = ["Москва", "Казань", "Пермь", "Сочи"]
print(cities[len(cities) - 1], cities[-1], cities[-4])
print(cities[-5])
Сочи Сочи Москва
Traceback (most recent call last):
  File "main.py", line 3, in <module>
    print(cities[-5])
          ~~~~~~^^^^
IndexError: list index out of range

Причина 2: лишний шаг в цикле

Цикл по индексам легко сделать на шаг длиннее списка — через range(len(...) + 1) или условие i <= len(...) в while. Все элементы печатаются, а на последнем шаге программа падает:

cities = ["Москва", "Казань", "Пермь", "Сочи"]
for i in range(len(cities) + 1):
    print(i, cities[i])
0 Москва
1 Казань
2 Пермь
3 Сочи
Traceback (most recent call last):
  File "main.py", line 3, in <module>
    print(i, cities[i])
             ~~~~~~^^^
IndexError: list index out of range

Надёжнее вовсе не считать индексы: for city in cities перебирает сами элементы, а если номер всё-таки нужен, его даёт enumerate:

cities = ["Москва", "Казань", "Пермь", "Сочи"]
for number, city in enumerate(cities, start=1):
    print(number, city)
1 Москва
2 Казань
3 Пермь
4 Сочи

Так выйти за границы невозможно. Подробнее о переборе — в статье про циклы.

Причина 3: список пустой

У пустого списка нет даже нулевого элемента. Обычно он пустеет незаметно: фильтр ничего не нашёл, файл оказался пустым, пользователь ничего не ввёл. Проверяй, что в списке что-то есть, до обращения к элементам — пустой список в условии считается ложью:

scores = []
print(max(scores) if scores else "оценок пока нет")
print(scores[0])
оценок пока нет
Traceback (most recent call last):
  File "main.py", line 3, in <module>
    print(scores[0])
          ~~~~~~^^^
IndexError: list index out of range

Причина 4: split() и sys.argv дали меньше, чем ждали

Строку из ввода часто делят методом split() и берут части по номерам. Если человек ввёл меньше слов, чем ожидала программа, второй части просто нет:

line = "Анна"
parts = line.split()
print(parts)
print("Фамилия:", parts[1])
['Анна']
Traceback (most recent call last):
  File "main.py", line 4, in <module>
    print("Фамилия:", parts[1])
                      ~~~~~^^^
IndexError: list index out of range

Проверь длину: if len(parts) < 2: print("Введи имя и фамилию через пробел"). О методах строк — в статье про split, join и другие методы.

Тот же случай с аргументами командной строки. sys.argv[0] — имя самой программы, а аргументы начинаются с sys.argv[1]. Запусти скрипт без аргументов — и первого из них нет:

import sys

print(sys.argv)
name = sys.argv[1]
['main.py']
Traceback (most recent call last):
  File "main.py", line 4, in <module>
    name = sys.argv[1]
           ~~~~~~~~^^^
IndexError: list index out of range

Проверяй len(sys.argv) и печатай подсказку, как запускать программу, — или возьми модуль argparse, который делает это сам.

Причина 5: элементы удаляют в цикле по индексам

Цикл for i in range(len(numbers)) вычисляет границы один раз, в начале. Если внутри удалять элементы, список становится короче, а индексы продолжают идти до старой длины:

numbers = [3, -1, 4, -5, 9]
for i in range(len(numbers)):
    if numbers[i] < 0:
        del numbers[i]
Traceback (most recent call last):
  File "main.py", line 3, in <module>
    if numbers[i] < 0:
       ~~~~~~~^^^
IndexError: list index out of range

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

numbers = [3, -1, 4, -5, 9]
positive = [n for n in numbers if n >= 0]
print(positive)
[3, 4, 9]

Вложенные списки: какой из индексов лишний

В таблице из списков два индекса: сначала строка, потом столбец. Если ошибка в такой строке, проверь оба — по длине внешнего списка и по длине строки:

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

Знаки ^ стоят под [2]: строки с индексом 2 нет, их всего две. Частая путаница — перепутать порядок и писать grid[столбец][строка].

Другие сообщения IndexError

Строки, кортежи и методы списков сообщают о той же ошибке своими словами. Отдельный случай — запись: присвоить значение несуществующему элементу нельзя, новый элемент добавляют методом append:

checks = [
    lambda: "Python"[10],
    lambda: (1, 2)[2],
    lambda: [].pop(),
]
for check in checks:
    try:
        check()
    except IndexError as exc:
        print(f"IndexError: {exc}")

marks = []
try:
    marks[0] = 5
except IndexError as exc:
    print(f"IndexError: {exc}")
marks.append(5)
print(marks)
IndexError: string index out of range
IndexError: tuple index out of range
IndexError: pop from empty list
IndexError: list assignment index out of range
[5]

Методы списков — append, pop, insert и другие — разобраны в статье о методах списков.

Как получить элемент без ошибки

Срезы за границы не падают: они просто возвращают то, что есть. А если нужен один элемент, который может отсутствовать, проверь длину и подставь значение по умолчанию:

cities = ["Москва", "Казань", "Пермь", "Сочи"]
print(cities[2:10])
print(cities[10:])
print(cities[5] if len(cities) > 5 else None)
['Пермь', 'Сочи']
[]
None

Оборачивать каждое обращение в try/except IndexError не стоит. Ошибка почти всегда значит, что программа неверно посчитала индекс или получила не те данные, а перехват это спрячет. try/except уместен там, где пустой ввод — нормальный сценарий, и ты знаешь, что делать дальше. Подробнее — в статье про try/except.

Частые вопросы

Как переводится list index out of range

«Индекс списка вне диапазона». Код обратился к элементу по номеру, которого в списке нет.

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

IndexError — нет элемента с таким номером в списке, строке или кортеже. KeyError — нет такого ключа в словаре. Безопасный способ взять значение из словаря — метод get, о нём в статье про словари.

Почему ошибка не на той строке, где я ошибся

Python падает там, где индекс использован, а посчитан он мог быть раньше: в цикле, в функции, из ввода. Выведи длину списка и индекс перед строкой с ошибкой и иди назад, к месту, где индекс получил это значение.

Источники

Выжимки статей в Telegram: одна ловушка, код с выводом и ссылка на полный разбор. t.me/koddo_ru