Что означает ошибка IndexError: list index out of range

Многогранная ошибка с коварным поведением.

Что означает ошибка IndexError: list index out of range

Ситуация: у нас есть проект, в котором мы математически моделируем игру в рулетку. Мы хотим обработать отдельно нечётные числа, которые есть на рулетке, — для этого нам нужно выбросить из списка все чётные. Проверка простая: если число делится на 2 без остатка — оно чётное и его можно удалить. Для этого пишем такой код:

# в рулетке — 36 чисел, не считая зеро
numbers = [n for n in range(36)]
# перебираем все числа по очереди
for i in range(len(numbers)):
    # если текущее число делится на 2 без остатка
    if numbers[i] % 2 == 0:
        # то убираем его из списка
        del numbers[i]

Но при запуске компьютер выдаёт ошибку:

❌ IndexError: list index out of range

Почему так произошло, ведь мы всё сделали правильно?

Что это значит: компьютер на старте цикла получает и запоминает одну длину списка с числами, а во время выполнения эта длина меняется. Компьютер, держа в памяти старую длину, пытается обратиться по номерам к тем элементам, которых уже нет в списке. 

Когда встречается: когда программа одновременно использует список как основу для цикла и тут же в цикле добавляет или удаляет элементы списка.

В нашем примере случилось вот что:

  1. Мы объявили список из чисел от 1 до 36.
  2. Организовали цикл, который зависит от длины списка и на первом шаге получает его размер.
  3. Внутри цикла проверяем на чётность, и если чётное — удаляем число из списка.
  4. Фактический размер списка меняется, а цикл держит в голове старый размер, который больше.
  5. Когда мы по старой длине списка обращаемся к очередному элементу, то выясняется, что список закончился и обращаться уже не к чему.
  6. Компьютер останавливается и выводит ошибку.

Что делать с ошибкой IndexError: list index out of range

Основное правило такое: не нужно в цикле изменять элементы списка, если список используется для организации этого же цикла. 

Если нужно обработать список, то результаты можно складывать в новую переменную, например так:

# в рулетке — 36 чисел, не считая зеро
numbers = [n for n in range(36)]
# новый список для нечётных чисел
new_numbers = []
# перебираем все числа по очереди
for i in range(len(numbers)):
    # если текущее число не делится на 2 без остатка
    if numbers[i] % 2 != 0:
        # то добавляем его в новый список
        new_numbers.append(numbers[i])

Художник:

Алексей Сухов

Корректор:

Ирина Михеева

Вёрстка:

Маша Климентьева

Вам может быть интересно
Uncaught TypeError: Cannot read property — что это означает

Нельзя прочитать то, чего нет.

medium
ReferenceError: math is not defined — что это означает

Противная и неочевидная ошибка, которую очень легко исправить.

medium
$ is not defined в jQuery: что это значит и что делать
medium
Как вернуть нужную тему, если сломался Вордпресс

Иногда сайты на Вордпрессе глючат и теряют внешний вид. Это можно исправить, но нужно кое-что знать

hard
Красивые ссылки на вашем сайте

Меняем стандартное подчёркивание на дизайнерское.

medium
Как работает быстрая сортировка

Ей уже 60 лет, но она до сих пор работает быстро

medium
Работа с файлами в Python: полное руководство по open(), readline() и записи данных

Как работать с разными текстовыми данными

easy
Пинг-понг против компьютера на JavaScript

Лёгкая версия

easy
Простейший генератор креативного текста

Без нейросетей, регистрации и СМС.

hard
easy
[anycomment]
Exit mobile version