Получение атрибутов через __getattribute__ в ООП в Python
Метод __getattribute__ вызывается при
каждой попытке прочитать атрибута объекта
через точку - и существующий, и
несуществующий, и приватный.
Имя запрошенного атрибута Python передает
в параметр name. Возвращаемое значение
метода считается результатом обращения
к атрибуту.
Внутри __getattribute__ нельзя писать
self.name - снова вызовется тот же
метод и получится бесконечная рекурсия.
Чтобы прочитать настоящее значение, нужен
вызов super().__getattribute__(name).
Скорее всего пока не очень понятно, как это
работает, поэтому давайте посмотрим на практическом
примере. Пусть у нас есть вот такой класс
Test с приватным и публичным
атрибутами:
class Test:
def __init__(self):
self.prop1 = 1 # публичный атрибут
self.__prop2 = 2 # приватный атрибут
Давайте добавим в наш класс метод
__getattribute__, который для начала
будет просто возвращать имя атрибута, к
которому произошло обращение:
class Test:
def __init__(self):
self.prop1 = 1
self.__prop2 = 2
def __getattribute__(self, name):
if name == 'prop1':
return super().__getattribute__(name)
return name # просто вернем имя атрибута
Давайте проверим работу созданного метода. Обратимся к трем типам атрибутов: к публичному атрибуту, к приватному и к несуществующему:
test = Test()
# Обращаемся к публичному атрибуту:
print(test.prop1) # выведет 1 - то есть значение атрибута
# Обращаемся к приватному атрибуту:
print(test.prop2) # выведет 'prop2' - имя атрибута
# Обращаемся к несуществующему атрибуту:
print(test.prop3) # выведет 'prop3' - имя атрибута
Для prop1 мы явно вызвали стандартное
чтение через super().__getattribute__.
Остальные имена метод вернул как строки.
Так видно, что __getattribute__
перехватывает любое обращение, а не только
«пропущенные», как __getattr__.