БэкендPython

AttributeError: object has no attribute в Python: где искать неверный объект или метод

Разбираем AttributeError object has no attribute: опечатки, неверный тип объекта, None, методы списков и строк, проверка type, repr и dir.

Кодик

Автор

5 мин чтения

AttributeError: object has no attribute означает, что объект слева от точки существует, но у его фактического типа нет запрошенного имени. Разделите выражение, выведите type(obj) и repr(obj), затем проверьте точное имя атрибута в документации или классе. Чаще всего виноваты опечатка, неожиданный тип или функция, которая вернула None.

В строке user.name.upper() есть два последовательных доступа: сначала user.name, затем upper у результата. Сообщение называет тип объекта и отсутствующий атрибут. Это позволяет не искать по всему проекту: нужно определить выражение непосредственно слева от проблемной точки и проследить, откуда оно пришло.

1Объект

Что фактически находится слева от точки в момент ошибки.

2Тип

Какие методы и поля реально поддерживает этот класс.

3Источник

Какая функция, ветка или преобразование создали значение.

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

Формулировка вида "list" object has no attribute "strip" уже сообщает две вещи: объект является списком, а код запросил строковый метод strip. Исправление зависит от намерения: выбрать один элемент, обработать каждую строку либо изменить функцию, которая должна была вернуть строку.

names = [' Анна ', ' Борис ']
print(type(names), repr(names))
# <class 'list'> [' Анна ', ' Борис ']

print(names.strip())
# AttributeError: 'list' object has no attribute 'strip'
СообщениеФактический объектПервый вопрос
'list' ... 'strip'СписокНужно обработать элемент или весь список?
'str' ... 'append'СтрокаПочему ожидался список?
'NoneType' ...NoneКакая функция ничего не вернула?
'dict' ... 'name'СловарьНужен ключ ["name"] или объект класса?
Class ...Экземпляр вашего классаСоздано ли поле во всех ветках конструктора?

Разбор типа объекта и имени атрибута в сообщении AttributeError
Сообщение сразу сужает поиск до фактического типа и одного отсутствующего имени.

Название типа важнее имени переменной. Переменная user может содержать словарь, строку или None. Имя выражает намерение автора, а type показывает состояние программы. Диагноз строится по фактическому значению в момент сбоя.

Проверка объекта слева от точки

Маршрут от строки к источнику
  1. Найдите последнюю строку вашего файла в Traceback.
  2. Определите имя атрибута из последней строки ошибки.
  3. Разбейте длинную цепочку точек на промежуточные переменные.
  4. Выведите type и repr объекта перед доступом.
  5. Найдите присваивание, аргумент или return, который создал значение.
  6. Повторите тот же сценарий после одной исправленной причины.

Для длинной цепочки временные переменные полезнее dir. Они показывают, на каком шаге тип перестал соответствовать ожиданию. dir(obj) можно использовать как подсказку в интерактивной отладке, но не как проверку бизнес-логики: список имён велик и включает внутренние методы.

profile = load_profile()
print(type(profile), repr(profile))

name = profile.get('name')
print(type(name), repr(name))

if name is not None:
    print(name.upper())

Путь значения от функции return до доступа к атрибуту
Промежуточные переменные показывают, на каком шаге тип стал неожиданным.

Ищите место изменения типа, а не ближайший похожий метод

Если profile оказался списком вместо словаря, замена get на случайный метод списка не исправит контракт. Проследите функцию load_profile и все её ветки return.

Почему NoneType не имеет нужного атрибута

None часто появляется, когда функция не выполнила return, метод изменяет объект на месте или поиск ничего не нашёл. Например, list.sort() сортирует список и возвращает None. Присваивание результата обратно переменной уничтожает ссылку на список.

Источник NoneПримерИсправление
Нет return в функцииvalue = save()Вернуть значение или не ожидать его
Метод меняет на местеitems = items.sort()Вызвать items.sort() отдельно
Поиск ничего не нашёлmatch = find(...)Обработать штатное отсутствие
Ветка без присваиванияЗначение осталось NoneПокрыть все ветки
Необязательное полеdict.getПроверить None или задать default
scores = [72, 91, 84]

# sort изменяет список и возвращает None
scores.sort()
print(scores)
# [72, 84, 91]

last_score = scores[-1]
print(last_score)
# 91

Источники None перед ошибкой AttributeError в Python
Нет return, in-place метод и пустой поиск требуют разных исправлений.

Не заменяйте None пустой строкой без контракта. Пустая строка тоже является данными и может пройти дальше как настоящее имя. Если значение обязательно, остановитесь с понятной ошибкой. Если отсутствие допустимо, ветка должна явно описывать, что делать без результата.

Опечатки и методы не того типа

У списков есть append, у строк strip, у словарей get. Похожие операции могут называться по-разному: строка не имеет push, а список не имеет length как свойства JavaScript. Сверяйтесь с документацией именно текущего языка и типа.

Добавлять hasattr везде

Проверка скрывает неожиданный тип. Сначала восстановите контракт данных.

Использовать dir как автозамену

Похожее имя метода может иметь другой смысл и набор аргументов.

Ловить AttributeError вокруг большого блока

Так можно скрыть опечатку внутри вызываемой функции, не связанную с исходным объектом.

Менять класс по сообщению

Часто неверен источник значения, а не определение класса. Проверьте место создания экземпляра.

Статическая подсказка редактора полезна до запуска

Понятные имена, type hints и небольшой контракт возвращаемого значения позволяют редактору подсветить часть ошибок заранее. Они не заменяют проверку входных данных, но уменьшают вероятность вызвать метод не того типа.

Практика: исправляем обработку списка имён

Если функция возвращает список строк, обработайте каждый элемент. Не вызывайте строковый метод у контейнера. Затем добавьте тест с пустым списком и строкой из одних пробелов. Так исправление подтверждает не только отсутствие AttributeError, но и правильный результат.

Чек-лист исправления
  1. Из сообщения выписаны фактический тип и отсутствующий атрибут.
  2. Длинная цепочка разбита на промежуточные значения.
  3. Перед проблемной точкой проверены type и repr.
  4. Найдено место, где объект создаётся или возвращается.
  5. Документация открыта для фактического типа, а не предполагаемого.
  6. Проверены обычное значение, пустой контейнер и None по контракту.
Исправление должно сохранить смысл операции. Для списка имён правильный код может быть [name.strip() for name in names], а не просто удаление .strip(). Запишите ожидаемый результат и сравните его после правки.
Короткие ответы
Что находится слева от точки в сообщении?

Объект, у которого Python пытался найти атрибут или метод.

Почему появляется NoneType?

Предыдущее выражение вернуло None: из-за отсутствующего return, метода in-place или штатного отсутствия результата.

Поможет ли hasattr всегда?

Нет. Он может скрыть нарушение контракта и пропустить нужную операцию.

Что возвращает list.sort?

None. Метод сортирует существующий список на месте.

Зачем использовать repr?

Он показывает точное представление значения, включая кавычки, пробелы и None.

Прослеживайте тип от источника до точки

Закрепите функции, коллекции и классы в курсе Python. Для словарей пригодится статья о словарях в Python, а для списков разбор первой суперсилы новичка.

Общий маршрут поиска повторите по материалу про частые ошибки. В Кодике удобно записывать ожидаемый тип рядом с реальным type и минимальной цепочкой присваиваний.