Ошибка AttributeError: has no attribute — причины и исправление

Ошибки Pythonобновлено 07.10.20269 мин чтенияесть тренажёр

AttributeError в Python — это ошибка, которая возникает, когда после точки написан метод или свойство, которого у этого значения нет. Три главные причины: метод чужого типа (append у строки), опечатка в названии (uper вместо upper) и None там, где ожидался список или строка.

Загружаем…

Что означает AttributeError в Python

AttributeError в Python — это ответ интерпретатора «у этого объекта нет такого атрибута». Атрибутом называют всё, что пишут через точку: методы вроде append() и свойства объекта.

В Python у каждого значения есть тип: строка, целое число, список, словарь. Тип определяет, какие действия доступны. Строку можно перевести в верхний регистр методом upper(), к списку можно добавить элемент методом append(), а у целого числа нет ни того, ни другого. Если попросить у значения чужое действие, программа остановится с AttributeError. Запустите код в редакторе выше: в нём спрятана одна из самых частых ловушек, и сообщение подскажет, где она.

slovo = "кот"
slovo.append("ы")
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    slovo.append("ы")
AttributeError: 'str' object has no attribute 'append'

Перевод простой: «у объекта типа str нет атрибута append». Встроенные типы и их методы перечислены в официальной документации Python[1], и при сомнении стоит заглянуть именно туда.

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

Сообщение AttributeError состоит из 2 важных частей: тип объекта в первых кавычках и имя атрибута во вторых. Оба нужны, чтобы понять, что исправлять.

Часть сообщенияПримерЧто из неё узнаём
Тип объекта'str', 'int', 'list', 'NoneType'Какое значение на самом деле лежит в переменной
Имя атрибута'append', 'uper'Что именно мы пытались вызвать
Подсказка Did you meanDid you mean: 'upper'?Похожее существующее имя — признак опечатки
Слово modulemodule 'math' has no attribute 'sqr'Опечатка в функции модуля

Подсказку «Did you mean» печатают новые версии Python, начиная с 3.10. В браузерном редакторе на сайте вместо неё появляется пояснение на русском, но смысл тот же. Если тип в сообщении удивил — например, вы ждали список, а там 'NoneType', — ошибка не в строке с точкой, а там, где переменной присвоили значение.

Метод не того типа

Чаще всего AttributeError появляется, когда метод одного типа вызывают у другого: append() у строки, upper() у числа, split() у списка. Таблица ниже помогает быстро свериться.

ТипЕсть методыНет методов (частые ошибки)
str (строка)upper, lower, strip, split, replace, find, countappend, sort, remove
list (список)append, insert, pop, remove, sort, reverse, countsplit, upper, add, push
int (целое число)почти нет методов для школьных задачupper, append, len, isdigit
dict (словарь)get, keys, values, items, popappend, add

Строки в Python неизменяемы, поэтому у них нет append(). Чтобы «добавить букву», создают новую строку сложением: slovo = slovo + "ы". Если нужно много изменений по одному символу, строку превращают в список, меняют его и склеивают обратно методом join(). Подробно методы строк показаны в уроке про строки в Python.

slovo = "кот"
slovo = slovo + "ы"
print(slovo)

bukvy = list("кот")
bukvy.append("ы")
print("".join(bukvy))

С числами похожая история. Вызывать у числа chislo.upper() или chislo.isdigit() не стоит — это не имеет смысла: проверка «состоит ли из цифр» нужна строке, а не числу. Обычно путаница возникает, когда переменную уже перевели через int(), а потом забыли об этом. Если нужен метод строки, сначала превратите число в строку: str(chislo). Разница между типами подробно разобрана в статье о типах данных Python.

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

Опечатка в названии — это вторая по частоте причина: uper вместо upper, lenght вместо len, apend вместо append. Python не угадывает, что вы имели в виду, и исправить имя за вас не получится.

Сюда же относятся методы из других языков. Тот, кто видел JavaScript, может написать spisok.push(5), но в Python добавление в конец называется append(). Также частая ошибка — spisok.length: длину в Python узнают функцией len(spisok), а не через точку. Регистр тоже важен: Upper() с большой буквы — другое имя, и его у строки нет.

imya = "аня"
print(imya.Capitalize())

Здесь правильное имя — capitalize() с маленькой буквы. По соглашению PEP 8 методы и функции называют маленькими буквами, а слова разделяют подчёркиванием[2]. Если в названии метода есть большая буква, это повод его перепроверить. Встроенные методы в документации Python тоже записаны только маленькими буквами.

«Если Python говорит, что метода нет, значит, нужно подключить модуль». Это миф: у встроенных типов все методы доступны сразу. Сообщение почти всегда означает опечатку или неверный тип, а импорт тут не поможет.

NoneType: когда вместо списка пусто

Сообщение 'NoneType' object has no attribute значит, что в переменной лежит None — специальное значение «ничего». Обычно его туда положили по ошибке строкой или 2 выше.

Самая известная ловушка — присвоить результат метода, который меняет список на месте. Методы append(), sort(), reverse() изменяют сам список и возвращают None. Запись veshi = veshi.append("спички") сначала добавит элемент, а затем заменит весь список на None. Следующая строка с точкой уже упадёт.

ocenki = [5, 3, 4]
print(ocenki.sort())
print(ocenki)

novye = sorted([5, 3, 4])
print(novye)
None
[3, 4, 5]
[3, 4, 5]

Если нужен новый отсортированный список, используйте функцию sorted(): она возвращает результат. Второй источник None — собственная функция без return. Она выполняет действия, но вызывающему коду отдаёт None, и попытка вызвать у результата метод закончится ошибкой. Как устроен возврат значения, показано в уроке про функции и return.

def privet(imya):
    return "Привет, " + imya

stroka = privet("Аня")
print(stroka.upper())

«None — это то же самое, что пустая строка или ноль». Это не подтверждается: у пустой строки есть все методы строк, у нуля — арифметика, а у None нет ни того, ни другого.

Как узнать, какие методы есть у объекта

Чтобы проверить тип значения, выведите type(x); чтобы увидеть список атрибутов — dir(x). Эти 2 функции снимают почти все вопросы.

x = 42
print(type(x))
print(type("кот"))
metody = [m for m in dir("") if not m.startswith("_")]
print(metody[:6])

Имена с подчёркиваниями в начале — служебные, новичку они не нужны, поэтому в примере они отфильтрованы. В IDLE список методов появляется сам: наберите имя переменной, точку и подождите — откроется подсказка. Это хороший способ не гадать, а выбирать из настоящих названий. Полный перечень методов строк, списков и словарей с описаниями приведён в документации Python, в разделе о встроенных типах. Документацию выпускает Python Software Foundation, и она обновляется вместе с каждой версией языка.

Как исправить AttributeError в Python пошагово

Чтобы исправить AttributeError в Python, достаточно 4 шагов: прочитать тип в сообщении, сравнить с ожидаемым, проверить написание и найти место, где переменная получила значение.

  1. Прочитать тип. Найдите в последней строке слово в первых кавычках: str, int, list, NoneType.
  2. Сравнить с ожиданием. Если тип не тот, что вы думали, исправлять нужно не метод, а присваивание выше.
  3. Проверить имя. Если тип правильный, сверьте написание метода по официальной документации или подсказке Did you mean.
  4. Искать None. При NoneType ищите строку вида x = x.sort() или функцию без return.

Если по ходу появилась другая ошибка, например TypeError при сложении строки с числом, это нормально: одна ошибка исправлена, и Python дошёл до следующей. Общий порядок чтения сообщений есть в статье как читать ошибки Python.

Когда переименование метода не поможет

Переименование метода не поможет, если в переменной лежит не тот объект. В этих 4 ситуациях менять нужно логику программы.

  • Переменную перезаписали 1 строкой выше. Например, s = len(s) превратило строку в число, и строковые методы пропали.
  • Функция возвращает None в 1 из веток. Если return стоит только внутри if, при ложном условии результат будет None.
  • Имя модуля совпало с именем файла. Файл random.py в папке проекта заменит настоящий модуль, и у него не найдётся ни 1 нужной функции.
  • Список из 2 уровней. Метод строки вызывают у вложенного списка: tablica[0].upper(), хотя tablica[0] — тоже список.

Чего делать нельзя

Нельзя подбирать методы наугад, пока ошибка не пропадёт: так легко получить код, который работает, но делает не то.

  • Нельзя присваивать результат append() или sort() той же переменной — получится None.
  • Не следует называть свои файлы именами модулей: turtle.py, random.py, math.py.
  • Не стоит использовать одну переменную сначала для строки, потом для числа: тип меняется, методы пропадают.
  • Не допускается переносить названия методов из других языков без проверки: push и length в Python не работают.
  • Не стоит прятать ошибку в try/except, не узнав тип объекта.

Источники

[1] The Python Tutorial (официальная документация Python 3). Python Software Foundation. — синтаксис и встроенные функции.

[2] van Rossum G., Warsaw B., Coghlan N. PEP 8 — Style Guide for Python Code. Python Software Foundation, 2001.

[3] Приказ Минпросвещения России от 18.05.2023 № 370 «Об утверждении федеральной образовательной программы основного общего образования». — информатика 7–9 (см. факты).

Вопросы и ответы

Что такое атрибут простыми словами?

Всё, что пишут после точки: метод, который что-то делает, или свойство, которое что-то хранит. У строки атрибуты одни, у списка другие.

Почему len пишут не через точку?

len() — встроенная функция, которая работает со строками, списками и словарями. Поэтому её вызывают отдельно: len(x), а не x.len().

Чем AttributeError в Python отличается от NameError?

NameError — нет самой переменной или функции. AttributeError — переменная есть, но у её значения нет того, что написано после точки.

Почему в сообщении написано NoneType?

Это тип значения None. Ищите место, где переменной присвоили результат метода, который ничего не возвращает, или функцию без return.

Изучают ли методы строк и списков в школе?

По федеральной образовательной программе обработку строк изучают в 8 классе, а одномерные массивы — в 9[3]. Конкретные методы зависят от выбранного языка; на Python это как раз upper, split, append.

Можно ли добавить свой метод к строке?

К встроенным типам — нет. Но можно написать свою функцию, которая принимает строку, или создать свой класс со своими методами — это следующая ступень после основ.