hasattr и поиск атрибутов в Python

hasattr и поиск атрибутов в Python

@python_quiz

Разберем этот квиз

Короткий пример:

python

Что печатает этот код и почему — разберём подробно.

Быстрая демонстрация

Запустите код: он выведет

То есть атрибут '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).

Анализ возможных сценариев (вариации)

  1. Атрибут в классе (как в примере)
python
  1. Атрибут только в экземпляре
python

Здесь у класса нет x, но у конкретного объекта есть.

  1. Переопределение экземпляром атрибута класса
python

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

  1. Дескрипторы и property
python

property — это атрибут класса, и он виден и на классе (как объект property) и на экземпляре (возвращает значение через __get__).

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

Краткие выводы

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

Эти знания полезны при отладке, при динамическом доступе к атрибутам и при проектировании классов с дескрипторами и специальными методами поиска атрибутов.

Report Page