Ошибка object is not subscriptable в Python — причины и решения
Если в Python вы видите ошибку «object is not subscriptable», значит вы пытаетесь индексировать объект, который не поддерживает операцию индексирования (например, float, int, bool, set). Сначала проверьте type(), затем либо преобразуйте значение в индексируемый тип (строку, список, кортеж, словарь), либо измените логику доступа. В статье — примеры, быстрые приёмы отладки и контрольные списки.

Что означает «subscriptable» в Python?
Термин «subscriptable» означает, что объект хранит несколько значений и поддерживает доступ к элементам по индексу через квадратные скобки []. К типичным индексируемым типам относятся: строки, списки, кортежи и словари.
Если вы попытаетесь применить индексирование к типу, который не поддерживает его, Python вызовет исключение TypeError: object is not subscriptable.
Короткое определение: subscriptable — объект, к которому можно обратиться через obj[index] для получения элемента.
Примеры индексируемых типов
list_example = [1, 3, 5, 'Idowu']
string_example = 'Idowu Omisola'
tuple_example = (1, 3, 5, 'Idowu')
dict_example = {'name': 'Idowu', 'Language': 'Yoruba'}
print(list_example[0]) # 1
print(string_example[3]) # w
print(tuple_example[1]) # 3
print(dict_example['name']) # IdowuПримеры типов, которые не поддерживают индексирование
Типы float, int, bool и set не позволяют обращаться к элементам по индексу. Попытка сделать это приведёт к TypeError.
float_example = 12.45
int_example = 12367
bool_example = True
set_example = {1, 3, 5, 'Python'}
print(float_example[1])
print(bool_example[2])
print(int_example[2])
print(set_example[2])Результат в терминале будет примерно таким:
Как исправить исключение
Шаг 1. Узнайте тип объекта перед индексированием. Это самый частый источник ошибки.
float_example = 12.45
int_example = 12367
bool_example = True
set_example = {1, 3, 5, 'Python'}
print(type(float_example)) #
print(type(int_example)) #
print(type(bool_example)) #
print(type(set_example)) # Шаг 2. Если объект не индексируем, преобразуйте его в индексируемый тип или измените способ доступа.
- Для чисел и булевых значений часто достаточно привести их к строке и затем выполнить срезы.
- Для множеств — преобразовать в список, если нужен доступ по индексу.
Примеры преобразований:
# Преобразование в строку для срезов
print(str(float_example)[:2]) # '12'
print(str(int_example)[:2]) # '12'
print(str(bool_example)[:2]) # 'Tr'
# Если нужно вернуть числовой тип после среза
converted_float = float(str(float_example)[:2])
converted_int = int(str(int_example)[:2])
print(converted_float, 'Data type:', type(converted_float)) # 12.0
print(converted_int, 'Data type:', type(converted_int)) # 12 Для множества используйте list() или сортировку, если требуется детерминированный порядок:
set_example = {1, 3, 5, 'Python'}
converted = sorted(set_example, key=lambda x: (isinstance(x, str), x))
print(converted[3]) # 'Python'Важно: list(set_example) извлечёт элементы, но порядок не гарантируется. Если порядок критичен, принимайте решение на основе контекста (см. раздел «Когда это не сработает»).
Альтернативные подходы
- Вместо индексирования используйте итерацию: for item in obj: … — это работает для итерируемых объектов.
- Для доступа к полям сложных структур используйте атрибуты или методы API, если объект — экземпляр класса, а не структурированный контейнер.
- Если данные приходят из внешнего API, разумно валидировать структуру (schema validation) до попытки индексирования.
Когда преобразование не помогает — контрпримеры
- Булев тип: str(True) даст ‘True’, а срезы вернут символы, не представляющие логически отдельные данные. Преобразование ломает семантику.
- float: срезы строки float теряют точность и смысл: 12.45 -> ‘12’ не равно округлению.
- set: если порядок важен, преобразование в список без дополнительной сортировки приведёт к непредсказуемым результатам.
Вывод: преобразование в индексируемый тип корректно, когда семантика доступа по индексу осмысленна.
Мини-методология отладки (быстрый набор действий)
- Воспроизведите ошибку локально с минимальным кодом.
- Добавьте print(type(obj)) перед местом обращения по индексу.
- Если type показывает неиндексируемый тип, решите: преобразовать или изменить доступ.
- Протестируйте крайние случаи: пустые значения, None, неожиданные типы.
- Напишите unit-тесты для функции, чтобы предотвратить регрессии.
Чек-листы по ролям
Для разработчика
- Проверить type() перед индексированием.
- Добавить валидацию входных данных.
- Обработать None и пустые коллекции.
- Добавить unit-тесты для граничных значений.
Для кода-ревьюера
- Есть ли явные приведения типов перед индексированием?
- Явно ли указана семантика преобразования (почему берётся [:2] и т.д.)?
- Нет ли скрытых предположений о порядке элементов множества?
Критерии приёмки
- Код не вызывает TypeError: object is not subscriptable при ожидаемых входных данных.
- Для некорректных входов функция возвращает понятную ошибку или значение по умолчанию.
- Unit-тесты покрывают случаи: индексируемый тип, неиндексируемый тип, None.
Однострочный глоссарий
- Subscriptable — объект, к которому можно обратиться через obj[index].
- Indexing — операция доступа к элементу по позиции или ключу через [].
Важно: нельзя полагаться на преобразование типов ради «быстрого фиксa», если это меняет смысл данных.
Итог
Понять причину ошибки «object is not subscriptable» просто: проверьте тип объекта и используйте подходящий способ доступа. Если нужно, преобразуйте тип аккуратно или перепроектируйте логику. Регулярная валидация входных данных и тесты заметно снижают шанс появления таких ошибок.
Дополнительно: используйте явную документацию функций и схемы данных для API-взаимодействий, чтобы заранее знать, какие типы приходят и какие операции над ними допустимы.
Похожие материалы
RDP: полный гид по настройке и безопасности
Android как клавиатура и трекпад для Windows
Советы и приёмы для работы с PDF
Calibration в Lightroom Classic: как и когда использовать
Отключить Siri Suggestions на iPhone