Обращения к атрибутам: __getattr__ и __setattr__ в Python

Метод __getattr__ выполняет операцию получения ссылки на атрибут. Если говорить более определенно, он вызывается с именем атрибута в виде строки всякий раз, когда обнаруживается попытка получить ссылку на неопределенный(несуществующий) атрибут.

Этот метод не вызывается, если интерпретатор может обнаружить атрибут посредством выполнения процедуры поиска в дереве наследования. Вследствие этого метод __getattr__ удобно использовать для обобщенной обработки запросов к атрибутам. Например:

В этом примере класс empty и его экземпляр X не имеют своих собственных атрибутов, поэтому при обращении к атрибуту X.age вызывается метод __getattr__ — в аргументе self передается экземпляр(X), а в аргументе attrname — строка с именем неопределенного атрибута («age»).

Класс выглядит так, как если бы он действительно имет атрибут age, возвращая результат обращения к имени X.age(40). В результате получается атрибут, вычисляемый динамически.

Для атрибутов, обработка которых классом не предусматривается, метод __getattr__ возбуждает встроенное исключение AttributeError, чтобы сообщить интерпретатору, что это действительно неопределенные имена. Поэтому попытка обращения к имени X.name приводит к появлению ошибки.

Родственник метода __getattr__ является метод перезагрузки __setattr__ который перехватывает все попытки присваивания зачений атрибутам. Если этот метод определен, выражение self.attr = value будет преобразовано в вызов метода self.__setattr__(‘attr’, value).

Работать с этим методом сложнее, потому что любая попытка выполнить присваивание любому атрибуту аргумента self приводит к повторному вызову метода __setattr__, вызывая бесконечный цикл рекурсивных вызовов(и, в конечном итоге, исключение переполнения стека!).

Если вам потребуется использовать этот метод, все присваивания в нем придется выполнять посредством словаря атрибутов. Используйте self.__dict__[‘name’] = x, а не self.name = x:

Эти два метода перезагрузки операций доступа к атрибутам позволяют контролировать или специализировать доступ к атрибутам в ваших объектах. Они могу играть весьма специфические роли.

PythonLearn

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *