Получение свойств через __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__.