TypeError: object is not subscriptable — как найти и исправить ошибку в Python

Что означает “subscriptable” в Python
Subscriptable — это объект, который хранит несколько значений или допускает доступ по индексам/ключам с помощью квадратных скобок ([]). Классические примеры: строка, список, кортеж, словарь. Если тип не поддерживает операцию индексирования, Python выбрасывает TypeError: object is not subscriptable.
Определение в одну строку: subscriptable = объект, у которого можно вызвать obj[index] или obj[key].
Какие типы индексируемы
Примеры индексируемых типов и простые обращения к элементам:
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]) # o
print(tuple_example[1]) # 3
print(dict_example["name"]) # IdowuПодсказка: у словаря индексирование происходит по ключу, а не по числовому индексу.
Типы, которые не поддерживают индексирование
Сюда относятся числа, булевы значения и множества. Попытка доступиться к ним через [] вызовет ту самую ошибку.
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])При выполнении вы увидите TypeError: ‘float’ object is not subscriptable (или аналогичный для int/bool/set).
Как отлаживать и разрешать ошибку: чеклист
- Выведите type(obj) для объекта, к которому применяете [].
- Подумайте: должен ли объект быть последовательностью или отображением? Если да — почему он не тот тип?
- Либо преобразуйте тип в индексируемый (str, list, tuple, dict), либо используйте другой способ доступа.
- Покройте преобразования тестами, чтобы не сломать поведение при изменении данных.
Пример проверки типа:
print(type(float_example)) #
print(type(int_example)) #
print(type(bool_example)) #
print(type(set_example)) # Преобразование типов, чтобы сделать их subscriptable
- Для чисел и булевых значений: преобразуйте в строку, затем индексируйте.
float_example = 12.45
int_example = 12367
bool_example = True
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, f"Data type: {type(converted_float)}") # 12.0,
print(converted_int, f"Data type: {type(converted_int)}") # 12, - Для множеств: преобразуйте в список. Учтите, что set не гарантирует порядок элементов. Если порядок важен, выполните сортировку с понятным ключом.
set_example = {1, 3, 5, "Python"}
converted = sorted(set_example, key=lambda x: (isinstance(x, str), x))
print(converted[3]) # 'Python'Важно: sorted при смешанных типах может выкинуть TypeError в Python 3, если элементы нельзя напрямую сравнить. Ключ сортировки должен быть надёжным для вашего набора данных.
Когда преобразование не подходит — альтернативы
- Вместо индексирования используйте итерацию: for x in obj: …
- Для доступа к полям объектов используйте getattr(obj, ‘field’, default).
- Если функция возвращает одиночное значение, а вы ждёте последовательность — исправьте функцию или оберните результат в список/tuple.
- Для работы с JSON проверьте, что библиотека вернула dict/list, а не строку: json.loads возвращает структуру, json.dumps — строку.
Частые причины ошибки в реальных проектах
- Вы ожидаете список из API, но получили None или пустую строку.
- Функция возвращает скаляр вместо коллекции.
- Путаница между bytes и str (bytes можно индексировать, но элементы — целые числа).
- Ошибка в использовании pandas: Series поддерживает индексирование по меткам, но DataFrame[…] возвращает столбец/серии — будьте внимательны с типами.
Ментальные модели и эвристики
- “Sequence vs Scalar”: если объект ведёт себя как контейнер (итерируем, len(obj) работает) — скорее всего subscriptable.
- “Mapping vs Sequence”: словарь — доступ по ключу, список/tuple — по целочисленному индексу.
- “Проверяй границы”: даже индексируемый объект может дать IndexError, если индекс вне диапазона.
Быстрая схема действий (SOP)
- Запустите print(type(obj)) и print(repr(obj)).
- Если это None — найдите, где он устанавливается.
- Если это скаляр и вам нужен элемент — преобразуйте в str или оберните в список, если это осмысленно.
- Если это set и важен порядок — используйте sorted с ключом или храните данные в list сразу.
- Добавьте тест, чтобы предотвратить регрессии.
Решение для разработчика: чек-лист перед PR
- Проверил тип переменных через type() в проблемном месте.
- Убедился, что API/функция возвращает ожидаемый тип.
- Добавил конвертацию типов с явными проверками и комментариями.
- Покрыл изменение тестом, проверяющим поведение при крайних данных.
Диаграмма принятия решения
flowchart TD
A[Есть ошибка 'object is not subscriptable'] --> B{Что за объект?}
B --> |None| C[Найти источник None]
B --> |int/float/bool| D[Нужно ли индексировать?]
D --> |Да| E[Преобразовать в str и индексировать, затем конвертировать]
D --> |Нет| F[Изменить логику доступа]
B --> |set| G[Преобразовать в list/sorted]
B --> |dict/list/str/tuple| H[Проверить индекс/ключ на корректность]Небольшой глоссарий
- Subscriptable: объект, к которому применяют [] для доступа.
- Sequence: упорядоченная коллекция (list, tuple, str).
- Mapping: отображение ключ→значение (dict).
Заключение
Ошибка “object is not subscriptable” обычно легко диагностируется: посмотрите на тип объекта и выберите одно из трёх решений — преобразовать тип, изменить логику доступа или исправить источник данных. Внимание к типам и простые проверки type()/repr() существенно ускоряют отладку.
Важно: не полагайтесь на неявные преобразования в продакшн-коде. Явные конверсии и тесты предотвращают подобные ошибки.
Похожие материалы
Как устроить идеальную вечеринку для просмотра ТВ
Как распаковать несколько RAR‑файлов сразу
Приватный просмотр в Linux: как и зачем
Windows 11 не видит iPod — способы исправить
PS5: как настроить игровые пресеты