Как использовать getattr для делегирования методов атрибутам?
У меня есть следующий класс:
class MyInt:
def __init__(self, v):
if type(v) != int:
raise ValueError('value must be an int')
self.v = v
def __getattr__(self, attr):
return getattr(self.v, attr)
i = MyInt(0)
print(i + 1)
Я получаю ошибку: TypeError: unsupported operand type(s) for +: 'MyInt' and 'int'
Не следует ли вызвать i.__add__(1)
? И не следует ли вызывать __getattr__
, когда такой метод не найден в классе MyInt
?
1 ответ:
__getattr__
Нельзя использовать для создания других магических методов. Вам нужно будет реализовать их все по отдельности.Когда внутренние части языка Python ищут магические методы, такие как
__add__
, они полностью обходят__getattr__
,__getattribute__
, и пример диктует. Поиск идет примерно так:def find_magic_method(object, method_name): for klass in type(object).__mro__: if method_name in klass.__dict__: return klass.__dict__[method_name] raise AttributeError
Если вы хотите увидеть точную процедуру поиска, это
_PyObject_LookupSpecial
вObjects/typeobject.c
.Если вам интересно, почему Python делает это, есть много магических методов, для которых это было бы действительно неловко или невозможно сделать то, что вы ожидали. Например, Python не может использовать
__getattribute__
для поиска__getattribute__
, так как это вызовет бесконечную рекурсию без базового случая.