AttributeError в Python: object has no attribute — как исправить
Что значит AttributeError: object has no attribute в Python и как её исправить: NoneType, str и list, module has no attribute, циклический импорт, __slots__.
Содержание · 10 разделов
- Как читать сообщение AttributeError
- ‘NoneType’ object has no attribute
- Функция ничего не вернула
- Метод изменяет объект на месте и возвращает None
- Поиск ничего не нашёл
- Как найти, откуда взялся None, заранее
- ‘str’, ‘list’, ‘dict’ object has no attribute: путаница типов
- Метод другого типа
- Опечатка и регистр: подсказка Did you mean
- Метод из другой версии Python или библиотеки
- Забыли скобки или await
- QuerySet и Manager в Django
- module has no attribute
- Свой файл называется как модуль
- Циклический импорт: partially initialized module
- Подмодуль не импортирован
- Атрибут удалён в новой версии
- Атрибуты класса и экземпляра
- Атрибут создаётся в методе, который не вызвали
- Забыли self или super().init()
- Атрибут экземпляра через класс: type object
- Два подчёркивания в начале имени
- property без сеттера
- slots запрещает новые атрибуты
- Как проверить атрибут: hasattr, getattr, dir
- Чек-лист: object has no attribute
- Частые вопросы
- Чем AttributeError отличается от NameError и TypeError?
- Почему редактор подсказывает метод, а при запуске AttributeError?
- Как обращаться к ключам словаря через точку?
- Почему ошибка появляется не при каждом запуске?
- Как узнать, какие методы есть у объекта?
- Итог
AttributeError: 'X' object has no attribute 'y' означает, что у объекта типа X нет атрибута или метода с именем y. Главная подсказка — тип в кавычках: он показывает, что на самом деле лежит в переменной. Если там 'NoneType', переменная равна None — функция ничего не вернула или поиск ничего не нашёл. Если 'str' или 'list' — в переменной другой тип, чем вы ожидали. Если module — Python импортировал не тот модуль или версию библиотеки, в которой этого имени нет.
Traceback (most recent call last):
File "C:\projects\app\users.py", line 9, in <module>
print(user.get("email"))
^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'get'
Быстрый порядок действий:
- Прочитайте тип в сообщении и сравните с тем, что ожидали.
- Если в конце есть
Did you mean: '...'?— это опечатка, исправьте имя. - Найдите строку, где переменная получила значение, и выясните, почему там оказался этот тип.
Ниже — разбор всех частых вариантов ошибки. Вывод получен запуском на Python 3.12 и 3.14. Как в целом читать traceback и искать нужный кадр, разобрано в статье ошибки в Python и traceback.
Как читать сообщение AttributeError
Атрибут — всё, к чему обращаются через точку: поле объекта (user.name), метод (text.upper), функция или класс модуля (math.sqrt). Python выбрасывает AttributeError, когда не может прочитать или присвоить такой атрибут. Форма сообщения подсказывает, где искать причину:
| Сообщение | Что означает |
|---|---|
'NoneType' object has no attribute 'get' | Переменная равна None |
'str' object has no attribute 'append' | У этого типа нет такого метода — путаница типов |
'User' object has no attribute 'usernme'. Did you mean: ... | Опечатка в имени |
type object 'User' has no attribute 'name' | Обращение к атрибуту экземпляра через класс |
module 'random' has no attribute 'randint' | Импортирован не тот модуль или имени нет в этой версии |
partially initialized module 'models' has no attribute 'User' | Циклический импорт |
property 'x' of 'C' object has no setter | Присваивание свойству, у которого нет сеттера |
'Point' object has no attribute 'z' при присваивании | В классе объявлены __slots__ |
Подчёркивание ^^^^ под строкой кода указывает на выражение, у которого не нашёлся атрибут. В цепочке a.b.c.d оно показывает, какое именно звено вернуло неожиданный объект.
‘NoneType’ object has no attribute
Самый частый вариант. NoneType — тип значения None, у которого почти нет атрибутов. Ошибка возникает не там, где появился None, а там, где к нему обратились, поэтому ищите строку выше, где переменной присвоили значение.
Функция ничего не вернула
Функция без return или с return только в одной ветке возвращает None:
def find_user(users, name):
for user in users:
if user["name"] == name:
return user
users = [{"name": "Анна", "email": "anna@example.com"}]
user = find_user(users, "Борис")
print(user.get("email"))
AttributeError: 'NoneType' object has no attribute 'get'
Пользователь не найден, цикл закончился, и функция неявно вернула None. Исправление зависит от логики: вернуть значение по умолчанию, выбросить исключение внутри функции или проверить результат перед использованием:
user = find_user(users, "Борис")
if user is None:
print("Пользователь не найден")
else:
print(user.get("email"))
Проверяйте именно is None: условие if user: пропустит и пустой словарь, и пустую строку, и 0.
Метод изменяет объект на месте и возвращает None
Методы, которые меняют объект на месте, возвращают None: list.sort(), list.append(), list.reverse(), list.extend(), dict.update(), random.shuffle(). Присваивание их результата затирает переменную:
nums = [3, 1, 2]
nums = nums.sort()
nums.append(4)
AttributeError: 'NoneType' object has no attribute 'append'
Вызывайте такие методы без присваивания или используйте функцию, которая возвращает новый объект:
nums = [3, 1, 2]
nums.sort() # сортирует на месте
sorted_nums = sorted(nums) # возвращает новый список
Строковые методы, наоборот, ничего не меняют на месте и всегда возвращают новую строку — text.strip() без присваивания ничего не сделает. Разница подробно разобрана в статье append в Python.
Поиск ничего не нашёл
Многие функции поиска возвращают None, если результата нет: re.match() и re.search(), dict.get(), метод find() в BeautifulSoup, .first() у QuerySet в Django.
import re
match = re.search(r"\d+", "заказ без номера")
print(match.group())
AttributeError: 'NoneType' object has no attribute 'group'
Код работает на одних данных и падает на других — поэтому ошибка «то есть, то нет». Проверьте результат перед использованием; оператор := позволяет сделать это в одной строке:
import re
if (match := re.search(r"\d+", "заказ без номера")) is not None:
print(match.group())
else:
print("Номер не найден")
Номер не найден
То же в Django: User.objects.filter(username="boris").first().email даёт 'NoneType' object has no attribute 'email', если такого пользователя нет. Способы безопасно получить один объект — в статье get() в Django ORM.
Как найти, откуда взялся None, заранее
Аннотации типов и статический анализатор находят такие места до запуска. Если функция может вернуть None, mypy предупредит об обращении к атрибуту без проверки:
import re
def first_number(text: str) -> str:
match = re.search(r"\d+", text)
return match.group()
orders.py:6: error: Item "None" of "Match[str] | None" has no attribute "group" [union-attr]
Ту же проверку выполняют Pylance в VS Code и PyCharm — подсвечивают строку прямо в редакторе. Как описывать необязательные значения (str | None), разобрано в статье типизация в Python.
‘str’, ‘list’, ‘dict’ object has no attribute: путаница типов
Если в сообщении встроенный тип, в переменной лежит не то, что вы думаете, или вы вызываете метод, которого у этого типа нет.
Метод другого типа
| Ошибка | Причина | Исправление |
|---|---|---|
'str' object has no attribute 'append' | Строка неизменяема, append есть у списка | s += "d" или собирать список и "".join() |
'list' object has no attribute 'split' | split есть только у строк | Вызвать для каждого элемента или для строки |
'list' object has no attribute 'lower' | То же: метод строки вызван у списка | [x.lower() for x in items] |
'dict' object has no attribute 'append' | Элементы словаря добавляют по ключу | d[key] = value |
'dict' object has no attribute 'name' | К ключам словаря нельзя обращаться через точку | d["name"] или d.get("name") |
'int' object has no attribute 'append' | Переменная-список перезаписана числом | Найти, где переменной присвоили число |
'tuple' object has no attribute ... | Лишняя запятая: x = 5, создаёт кортеж | Убрать запятую |
'list' object has no attribute 'shape' | Обычный список вместо массива NumPy | np.array(data) |
Чтобы узнать, что лежит в переменной, напечатайте тип прямо перед строкой с ошибкой:
print(type(items), repr(items))
Частая ситуация — функция возвращает разные типы в зависимости от данных: например, json.loads() даёт список, если в JSON массив, и словарь, если объект.
Опечатка и регистр: подсказка Did you mean
С Python 3.10 интерпретатор ищет похожее имя и добавляет подсказку к сообщению:
s = "abc"
s.Upper()
AttributeError: 'str' object has no attribute 'Upper'. Did you mean: 'upper'?
Подсказка работает и для ваших классов, и для модулей:
AttributeError: 'User' object has no attribute 'usernme'. Did you mean: 'username'?
AttributeError: module 'math' has no attribute 'sqr'. Did you mean: 'sqrt'?
Имена в Python чувствительны к регистру: upper и Upper — разные атрибуты. Подсказку добавляет механизм вывода traceback, в str(e) её нет: если логировать только текст исключения, подсказка потеряется. В IPython и Jupyter подсказка может не выводиться, если оболочка показывает ошибки своим способом. В Python 3.9 и более ранних подсказок нет — сверяйте имя по dir(obj).
Метод из другой версии Python или библиотеки
Код из старой статьи или ответа на форуме вызывает метод, которого больше нет:
| Ошибка | Что изменилось | Замена |
|---|---|---|
'str' object has no attribute 'decode'. Did you mean: 'encode'? | В Python 3 str уже текст, decode есть у bytes | Убрать .decode() или вызвать его у bytes |
'dict' object has no attribute 'iteritems' | Метод Python 2 | d.items() |
'DataFrame' object has no attribute 'append' | Удалён в pandas 2.0 | pd.concat([df, new_df]) |
'WebDriver' object has no attribute 'find_element_by_id' | Методы find_element_by_* убраны из Selenium 4 | driver.find_element(By.ID, "id") |
Если метод «точно есть» в документации, проверьте установленную версию библиотеки: python -m pip show pandas.
Забыли скобки или await
Без скобок вы обращаетесь к самой функции, а не к её результату:
class User:
def get_name(self):
return "Анна"
User().get_name.upper()
AttributeError: 'function' object has no attribute 'upper'
Нужно User().get_name().upper(). Похожая ошибка в асинхронном коде — вызов корутины без await:
import asyncio
async def fetch_user():
return {"name": "Анна"}
async def main():
user = fetch_user()
print(user.get("name"))
asyncio.run(main())
AttributeError: 'coroutine' object has no attribute 'get'
sys:1: RuntimeWarning: coroutine 'fetch_user' was never awaited
Исправление — user = await fetch_user().
QuerySet и Manager в Django
filter() возвращает набор объектов (QuerySet), а не один объект, поэтому поле модели у него не прочитать:
AttributeError: 'QuerySet' object has no attribute 'email'
AttributeError: 'UserManager' object has no attribute 'email'
Первая ошибка — User.objects.filter(...).email, вторая — User.objects.email. Для одного объекта используйте get() или first(), для набора — цикл.
module has no attribute
Сообщение module 'X' has no attribute 'Y' значит, что модуль импортировался, но имени Y в нём нет. Сначала выясните, какой файл Python загрузил:
import random
print(random.__file__)
Если путь ведёт в папку вашего проекта, а не в стандартную библиотеку или site-packages, модуль затенён вашим файлом.
Свой файл называется как модуль
Python ищет модули сначала в папке запускаемого скрипта, поэтому файл random.py, requests.py или datetime.py в проекте подменяет настоящий модуль:
my_project/
├── game.py # import random
└── random.py # ваш файл с тем же именем
import random
print(random.randint(1, 6))
На Python 3.12 сообщение не объясняет причину:
AttributeError: module 'random' has no attribute 'randint'
С Python 3.13 интерпретатор подсказывает сам:
AttributeError: module 'random' has no attribute 'randint' (consider renaming 'C:\projects\app\random.py' since it has the same name as the standard library module named 'random' and prevents importing that standard library module)
Для сторонних библиотек подсказка появляется, когда сам запускаемый скрипт назван как библиотека (requests.py с import requests внутри): ... (consider renaming '...\requests.py' if it has the same name as a library you intended to import). Если затеняющий файл лежит рядом со скриптом, Python 3.13+ промолчит.
Исправление: переименуйте свой файл (random_game.py, my_requests.py) и удалите папку __pycache__ рядом с ним. Проверьте также папки-пакеты: каталог requests/ с __init__.py затеняет библиотеку так же, как файл.
Циклический импорт: partially initialized module
Модуль models импортирует utils, а utils — models:
# models.py
import utils
class User:
def __init__(self, name):
self.name = utils.normalize(name)
# utils.py
import models
DEFAULT_USER = models.User("гость")
def normalize(name):
return name.strip().title()
При import models Python начинает выполнять models.py, на первой строке переходит в utils.py, а тот обращается к models.User, которого ещё нет: models.py выполнен только до первой строки.
Traceback (most recent call last):
File "C:\projects\app\app.py", line 1, in <module>
import models
File "C:\projects\app\models.py", line 1, in <module>
import utils
File "C:\projects\app\utils.py", line 3, in <module>
DEFAULT_USER = models.User("гость")
^^^^^^^^^^^
AttributeError: partially initialized module 'models' has no attribute 'User' (most likely due to a circular import)
На Python 3.14 для модулей из папки проекта сообщение выглядит иначе: module 'models' has no attribute 'User' (consider renaming '...\models.py' if it has the same name as a library you intended to import). Слов про циклический импорт в нём нет, но цепочка import в traceback — app.py → models.py → utils.py → снова models — выдаёт цикл.
Способы исправить, от лучшего к компромиссному:
-
Разорвать цикл. Перенесите код, который нужен обоим модулям, в один из них или в третий модуль. Здесь
utilsне должен знать оmodels:DEFAULT_USERпереезжает вmodels.py. -
Импортировать внутри функции. Импорт выполнится при вызове, когда оба модуля уже загружены:
# utils.py def default_user(): import models # импорт выполняется при вызове функции return models.User("гость") -
Только для аннотаций типов —
from __future__ import annotationsи импорт подif TYPE_CHECKING:.
Тот же текст ошибки бывает и при затенении: файл logging.py в пакете ломает импорт стандартного logging внутри библиотек, и traceback заканчивается partially initialized module. Если в цепочке импортов есть ваш файл с именем стандартного модуля — переименуйте его. Ошибки вида cannot import name ... (most likely due to a circular import) — тот же цикл при from X import Y, они разобраны в статье ImportError в Python.
Подмодуль не импортирован
Пакет не загружает свои подмодули автоматически:
import xml
tree = xml.etree.ElementTree.fromstring("<a/>")
AttributeError: module 'xml' has no attribute 'etree'
Импортируйте подмодуль явно: import xml.etree.ElementTree as ET. Код без явного импорта иногда работает — если подмодуль уже загрузила другая библиотека. Тем коварнее ошибка: она появляется после обновления зависимостей. Так же устроены os.path (загружается вместе с os) и, например, concurrent.futures (не загружается).
Похожая путаница с datetime: модуль и класс называются одинаково.
| Импорт | Как вызвать |
|---|---|
import datetime | datetime.datetime.now() |
from datetime import datetime | datetime.now() |
import datetime с вызовом datetime.now() даёт module 'datetime' has no attribute 'now'.
Атрибут удалён в новой версии
Библиотеки удаляют устаревшие имена, и код, написанный под старую версию, падает:
AttributeError: module 'collections' has no attribute 'Mapping'
Абстрактные классы Mapping, Iterable и другие убраны из модуля collections в Python 3.10 — импортируйте их из collections.abc. NumPy 1.24 удалил псевдонимы np.float, np.int, np.object, np.complex, np.str и сам объясняет замену:
AttributeError: module 'numpy' has no attribute 'float'.
`np.float` was a deprecated alias for the builtin `float`. To avoid this error in existing code, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.
Что делать: найдите имя в changelog библиотеки и замените вызов. Если код чужой и переписать его нельзя, зафиксируйте совместимую версию в окружении: python -m pip install "numpy<1.24". Это временная мера — новые версии Python старые сборки библиотек могут не поддерживать.
Атрибуты класса и экземпляра
В своих классах ошибка почти всегда значит, что атрибут не был создан к моменту обращения. Основы классов — в статье классы в Python.
Атрибут создаётся в методе, который не вызвали
class Cart:
def load(self):
self.items = [1]
cart = Cart()
print(cart.items)
AttributeError: 'Cart' object has no attribute 'items'
self.items появится только после cart.load(). Создавайте все атрибуты в __init__, хотя бы со значением None или пустой коллекцией, — тогда объект всегда в предсказуемом состоянии.
Забыли self или super().init()
Присваивание без self. создаёт локальную переменную метода, а не атрибут:
class User:
def __init__(self, name):
name = name # нужно self.name = name
User("Анна").name даст 'User' object has no attribute 'name'. Та же ошибка возникает в наследнике, который переопределил __init__ и не вызвал родительский:
class Animal:
def __init__(self, name):
self.name = name
class Dog(Animal):
def __init__(self, name, breed):
self.breed = breed # не вызван super().__init__(name)
dog = Dog("Шарик", "дворняга")
print(dog.name)
AttributeError: 'Dog' object has no attribute 'name'
Добавьте первой строкой super().__init__(name).
Атрибут экземпляра через класс: type object
AttributeError: type object 'User' has no attribute 'name'
Слова type object означают, что обращаются к самому классу (User.name), а не к объекту (User("Анна").name). Атрибуты, созданные через self в __init__, есть только у экземпляров. Создайте объект или, если значение общее для всех, объявите атрибут класса в теле класса.
Два подчёркивания в начале имени
Атрибуты вида self.__balance Python переименовывает внутри класса в _Account__balance (это называется name mangling — искажение имён), поэтому снаружи по исходному имени их не найти:
class Account:
def __init__(self):
self.__balance = 100
acc = Account()
print(acc.__balance)
AttributeError: 'Account' object has no attribute '__balance'
Для внутренних атрибутов обычно хватает одного подчёркивания: self._balance доступен снаружи, но по соглашению считается внутренним.
property без сеттера
Свойство, объявленное через @property, по умолчанию только для чтения:
AttributeError: property 'x' of 'C' object has no setter
Добавьте сеттер через @x.setter или меняйте внутренний атрибут, который свойство возвращает. Такой текст сообщения — с Python 3.11; в Python 3.10 было can't set attribute 'x'.
slots запрещает новые атрибуты
Если в классе объявлены __slots__, у объектов нет словаря __dict__, и создать атрибут вне списка нельзя:
class Point:
__slots__ = ("x", "y")
def __init__(self, x, y):
self.x = x
self.y = y
p = Point(1, 2)
p.z = 3
Python 3.12:
AttributeError: 'Point' object has no attribute 'z'
Python 3.14 уточняет причину:
AttributeError: 'Point' object has no attribute 'z' and no __dict__ for setting new attributes
Добавьте имя в __slots__ или уберите __slots__, если экономия памяти не нужна. Слот, объявленный, но не заполненный, тоже даёт AttributeError при чтении — присвойте значение в __init__. Так же ведут себя датаклассы с @dataclass(slots=True).
Как проверить атрибут: hasattr, getattr, dir
Эти функции нужны, когда атрибута может не быть по смыслу задачи: необязательные поля, объекты разных классов, имя атрибута в переменной.
class User:
def __init__(self, name):
self.name = name
user = User("Анна")
print(hasattr(user, "name"), hasattr(user, "email"))
print(getattr(user, "email", "не указан"))
field = "name"
print(getattr(user, field))
True False
не указан
Анна
| Способ | Когда использовать |
|---|---|
hasattr(obj, "name") | Проверить наличие перед действием |
getattr(obj, "name", default) | Прочитать со значением по умолчанию; имя атрибута в переменной |
try / except AttributeError | Атрибут обычно есть, отсутствие — редкий случай |
dir(obj), vars(obj), type(obj) | Отладка: какие атрибуты есть у объекта и какого он типа |
getattr без третьего аргумента ведёт себя как обычная точка и выбрасывает AttributeError. vars(user) вернёт {'name': 'Анна'} — атрибуты конкретного экземпляра, а dir(user) — все доступные имена, включая методы класса.
С Python 3.10 у исключения есть атрибуты name (имя, которое не нашлось) и obj (объект, у которого его искали) — удобно для логов:
try:
user.email
except AttributeError as e:
print(e.name, type(e.obj).__name__)
email User
Важно:
hasattr,getattrс умолчанием иexcept AttributeErrorне исправляют ошибку, а прячут её. Если атрибут должен быть, ищите, почему его нет: значение по умолчанию вместоNoneиз пустого результата поиска превратит понятное падение в неверные данные дальше по коду. Как перехватывать исключения точечно, разобрано в статье try/except в Python.
Чек-лист: object has no attribute
- Прочитайте тип в кавычках.
NoneType— ищите, где переменная получилаNone. Встроенный тип — проверьтеtype()переменной. - Есть
Did you mean— исправьте опечатку или регистр. module ... has no attribute— напечатайтемодуль.__file__: не ваш ли это файл с тем же именем.partially initialized module— найдите цикл в цепочкеimportв traceback.- Метод описан в документации, но его нет — сверьте версию Python или библиотеки.
- Свой класс — проверьте, создаётся ли атрибут в
__init__, есть лиself.иsuper().__init__().
Частые вопросы
Чем AttributeError отличается от NameError и TypeError?
NameError — Python не знает имени вообще: переменная не создана или опечатка в ней. AttributeError — объект есть, но у него нет атрибута после точки. TypeError — операция не подходит типу объекта: сложение строки с числом, вызов функции с неверными аргументами. Частые случаи разобраны в статье TypeError в Python.
Почему редактор подсказывает метод, а при запуске AttributeError?
Редактор и терминал используют разные интерпретаторы или окружения, а в них — разные версии библиотеки. Сравните sys.executable в скрипте с интерпретатором, выбранным в IDE, и версию пакета через python -m pip show имя_пакета. Если версия старая, обновите её в нужном окружении.
Как обращаться к ключам словаря через точку?
Обычный dict этого не умеет. Для фиксированного набора полей используйте types.SimpleNamespace, датакласс или модель Pydantic:
from types import SimpleNamespace
config = SimpleNamespace(**{"debug": True, "port": 8000})
print(config.port) # → 8000
Для произвольных данных из JSON надёжнее оставить словарь и d["key"] / d.get("key").
Почему ошибка появляется не при каждом запуске?
Обычно это 'NoneType' object has no attribute: функция поиска иногда ничего не находит — пустой ответ API, не тот HTML на странице, отсутствующая запись в базе. Сохраните входные данные, на которых код упал, и добавьте проверку на None в месте, где значение получено.
Как узнать, какие методы есть у объекта?
dir(obj) выводит все доступные имена, help(obj.method) — описание метода. Отфильтровать служебные имена можно так: [a for a in dir(obj) if not a.startswith("_")]. В интерактивном режиме и в редакторе то же самое показывает автодополнение после точки.
Итог
AttributeError всегда сообщает, какой тип оказался в переменной и какое имя не нашлось. 'NoneType' — значение потерялось раньше: функция без return, метод вроде sort(), пустой результат поиска. Встроенный тип — путаница типов, опечатка (Python 3.10+ подсказывает Did you mean) или метод из другой версии. module has no attribute — свой файл с именем модуля, циклический импорт, неимпортированный подмодуль или удалённое API. В своих классах проверяйте __init__, self, super() и __slots__. Другие исключения и общий порядок отладки — в разделе «Ошибки и исключения» и в руководстве по чтению traceback.
- #Python
- #AttributeError
- #Исключения
- #Отладка
- #Классы