Что означает 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 mean | Did you mean: 'upper'? | Похожее существующее имя — признак опечатки |
| Слово module | module 'math' has no attribute 'sqr' | Опечатка в функции модуля |
Подсказку «Did you mean» печатают новые версии Python, начиная с 3.10. В браузерном редакторе на сайте вместо неё появляется пояснение на русском, но смысл тот же. Если тип в сообщении удивил — например, вы ждали список, а там 'NoneType', — ошибка не в строке с точкой, а там, где переменной присвоили значение.
Метод не того типа
Чаще всего AttributeError появляется, когда метод одного типа вызывают у другого: append() у строки, upper() у числа, split() у списка. Таблица ниже помогает быстро свериться.
| Тип | Есть методы | Нет методов (частые ошибки) |
| str (строка) | upper, lower, strip, split, replace, find, count | append, sort, remove |
| list (список) | append, insert, pop, remove, sort, reverse, count | split, upper, add, push |
| int (целое число) | почти нет методов для школьных задач | upper, append, len, isdigit |
| dict (словарь) | get, keys, values, items, pop | append, 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 шагов: прочитать тип в сообщении, сравнить с ожидаемым, проверить написание и найти место, где переменная получила значение.
- Прочитать тип. Найдите в последней строке слово в первых кавычках: str, int, list, NoneType.
- Сравнить с ожиданием. Если тип не тот, что вы думали, исправлять нужно не метод, а присваивание выше.
- Проверить имя. Если тип правильный, сверьте написание метода по официальной документации или подсказке Did you mean.
- Искать 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.
Можно ли добавить свой метод к строке?
К встроенным типам — нет. Но можно написать свою функцию, которая принимает строку, или создать свой класс со своими методами — это следующая ступень после основ.