Метод __getattr__ выполняет операцию получения ссылки на атрибут. Если говорить более определенно, он вызывается с именем атрибута в виде строки всякий раз, когда обнаруживается попытка получить ссылку на неопределенный(несуществующий) атрибут.
Этот метод не вызывается, если интерпретатор может обнаружить атрибут посредством выполнения процедуры поиска в дереве наследования. Вследствие этого метод __getattr__ удобно использовать для обобщенной обработки запросов к атрибутам. Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
>>> class empty: def __getattr__(self, attrname): if attrname == "age": return 40 else: raise AttributeError, attrname ... ... >>> X = empty() >>> X.age 40 >>> X.name ...текст сообщения об ошибке опущен... AttributeError: name |
В этом примере класс 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).
Как раскрутить Аск фм своими силами и платно, об этом пишет блог pricesmm.com. Если вы пока не в курсе, то узнаете, чем интересна эта сеть и для чего её раскручивать. Как получить лайки Аск фм разными способами, в том числе и на платном сервисе – автор изучил и проверил лично. Знакомьтесь с опытом.
Работать с этим методом сложнее, потому что любая попытка выполнить присваивание любому атрибуту аргумента self приводит к повторному вызову метода __setattr__, вызывая бесконечный цикл рекурсивных вызовов(и, в конечном итоге, исключение переполнения стека!).
Если вам потребуется использовать этот метод, все присваивания в нем придется выполнять посредством словаря атрибутов. Используйте self.__dict__[‘name’] = x, а не self.name = x:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
>>> class AccessControl: def __setattr__(self, attr, value): if attr == 'age': self.__dict__[attr] = value else: raise AttributeError, attr + ' not allowed' ... ... >>> X = AccessControl() >>> X.age = 40 # Вызовет метод __setattr__ 40 >> X.name = 'pythonlearn' ...текст об ошибке был опущен... AttributeError: name not allowed |
Эти два метода перезагрузки операций доступа к атрибутам позволяют контролировать или специализировать доступ к атрибутам в ваших объектах. Они могу играть весьма специфические роли.