Ответ
В Python доступ к атрибутам объекта — это строго определенный процесс, который включает несколько шагов и специальных (магических) методов.
Порядок поиска атрибута (obj.x):
-
Вызов
__getattribute__(self, name)Этот метод вызывается при любом обращении к атрибуту. Если он определен в классе, он перехватывает все обращения. Его нужно реализовывать с осторожностью, чтобы избежать бесконечной рекурсии.class Logger: def __getattribute__(self, name): print(f"Доступ к атрибуту: {name}") # Важно вызвать родительскую реализацию, чтобы получить значение return super().__getattribute__(name) -
Поиск в словаре экземпляра (
obj.__dict__) Если__getattribute__не переопределен (или вызываетsuper()), Python ищет атрибут в словаре__dict__самого экземпляра. -
Поиск в атрибутах класса и родительских классов Если атрибут не найден в
__dict__, поиск продолжается в атрибутах класса (type(obj)) и далее по иерархии родительских классов в соответствии с MRO (Method Resolution Order). Здесь находятся методы и переменные класса. -
Вызов
__getattr__(self, name)Этот метод вызывается только в том случае, если атрибут не был найден ни на одном из предыдущих шагов. Это удобный механизм для реализации динамических атрибутов.class DynamicAttributes: def __getattr__(self, name): # Вызывается, только если 'value' не существует return f"Атрибут '{name}' не найден, возвращаем динамическое значение." d = DynamicAttributes() print(d.value) # Вывод: Атрибут 'value' не найден...
Для программного доступа также используется встроенная функция getattr(object, name[, default]), которая проходит тот же путь поиска и может возвращать значение по умолчанию, если атрибут не найден.