hasattr и поиск атрибутов в Python
@python_quizРазберем этот квиз
Короткий пример:

Что печатает этот код и почему — разберём подробно.
Быстрая демонстрация
Запустите код: он выведет

То есть атрибут 'x' существует и для класса A, и для его экземпляра A().
Как работает hasattr и порядок поиска атрибутов
- hasattr(obj, name) использует getattr(obj, name) внутри и возвращает True, если getattr не выбросил
AttributeError. - Поиск атрибута для экземпляра идёт так:
1. Сначала проверяется словарь экземпляра (obj.__dict__).
2. Если не найдено — поиск продолжается в классе (type(obj)) и в базовых классах.
3. При нахождении дескриптора (например, property) применяется соответствующий протокол descriptor.
- Поиск атрибута для самого класса (когда obj — это класс) проверяет атрибуты класса и базовых классов (и участвуют механизмы метакласса при обращении к атрибуту класса).
В нашем примере атрибут x объявлен в теле класса A, поэтому:
- hasattr(A, 'x') возвращает True (атрибут найден в классе),
- hasattr(A(), 'x') также возвращает True (поиск на экземпляре падает на класс и находит x).
Анализ возможных сценариев (вариации)
- Атрибут в классе (как в примере)

- Атрибут только в экземпляре

Здесь у класса нет x, но у конкретного объекта есть.
- Переопределение экземпляром атрибута класса

Экземпляр может «затенять» значение, но наличие атрибута для обоих остаётся True.
- Дескрипторы и property

property — это атрибут класса, и он виден и на классе (как объект property) и на экземпляре (возвращает значение через __get__).
- Когда hasattr возвращает False (или может выбросить исключение)
- Если getattr генерирует
AttributeError— hasattr вернёт False. - Если getattr генерирует другое исключение — оно будет проброшено наружу (hasattr не подавляет не-
AttributeError).

Краткие выводы
- hasattr проверяет существование атрибута с помощью getattr, и для экземпляра поиск падает на класс, если атрибута нет в экземпляре.
- Поэтому атрибут, объявленный в классе, будет виден и через класс, и через его экземпляры.
- Будьте внимательны с
__getattr__/__getattribute__— если они бросают исключения, это влияет на поведение hasattr.
Эти знания полезны при отладке, при динамическом доступе к атрибутам и при проектировании классов с дескрипторами и специальными методами поиска атрибутов.