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

Jon*_*ung 4 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)
Run Code Online (Sandbox Code Playgroud)

我收到错误: TypeError: unsupported operand type(s) for +: 'MyInt' and 'int'

i.__add__(1)应该叫吗?__getattr__当在MyInt类中找不到这样的方法时不应该调用吗?

use*_*ica 7

__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
Run Code Online (Sandbox Code Playgroud)

如果您想查看确切的查找过程,它_PyObject_LookupSpecialObjects/typeobject.c.

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

  • 真正的查找和Python代码之间的区别在于,上面的Python代码可以使用元类来操作以提供自定义的“__dict__”,而真正的查找甚至绕过元类并通过直接字段访问“__dict__”映射在底层 C 结构中。 (2认同)