如何使用__getattr__将方法委托给属性?

时间:2016-07-10 17:59:35

标签: python composition 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 个答案:

答案 0 :(得分:4)

__getattr__不能用于生成其他魔术方法。您需要单独实施所有这些内容。

当Python语言内部查找__add__等魔术方法时,它们会完全绕过__getattr____getattribute__和实例dict。查找大致类似于

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

如果您想查看完整的查找程序,请Objects/typeobject.c中的_PyObject_LookupSpecial

如果您想知道为什么Python会这样做,那么有许多神奇的方法可能会让您感到尴尬或不可能做到您所期望的。例如,Python无法使用__getattribute__来查找__getattribute__,因为这会导致无限递归而没有基本情况。