a.__getattr__
вызывается, только если атрибут не найден в a.__dict__
.
a.__getattribute__
вызывается во всех случаях, если оно определено.
Как вы знаете, a.__getattribute__(attr)
является синтаксическим сахаром для type(a).__getattribute__(a, attr)
, но, поскольку этот метод не определен в testAttrAccess
, вызывается родительский метод object.__getattribute__(a, attr)
. Исходя из ваших результатов, мы можем сделать вывод, что не object.__getattribute__
вызывает __getattr__
. Вероятно, об этом позаботится переводчик.
Вы можете заставить свою программу работать, изменив ее следующим образом:
class testAttrAccess(object):
def __init__(self):
self.data = {"attr1": "value1", "attr2": "value2"}
def __getattribute__(self, name):
try:
return object.__getattribute__(self, name)
except AttributeError:
if name == "__getattr__":
return object.__getattribute__(self, "__getattribute__")
try:
return object.__getattribute__(self, "data")[name]
except KeyError:
raise AttributeError
a = testAttrAccess()
print a.attr2
print a.__getattr__('attr2')
print a.__getattribute__('attr2')
print a.qwerty
Выход:
value2
value2
value2
Traceback (most recent call last):
File "test.py", line 20, in
print a.qwerty
File "test.py", line 13, in __getattribute__
raise AttributeError
AttributeError