为什么python中的__getattr__实现没有拦截魔术方法?

yas*_*aka 4 python indexing containers magic-methods getattr

主语

例子:

MyList(object):

    def __init__(self, list_to_be_wrapped):
          self._items = list_to_be_wrapped

    def __getattr__(self, item):
          return getattr(self._items, item)
Run Code Online (Sandbox Code Playgroud)

然后

MyList([1, 2, 3])[-1]
Run Code Online (Sandbox Code Playgroud)

将提高: TypeError: ‘MyList’ object does not support indexing

尽管:

MyList([1, 2, 3]).pop()
Run Code Online (Sandbox Code Playgroud)

将完美运行(pop将被拦截__getattr__并重定向到_items

在我看来,__getattr__考虑到“通过组合而不是继承实现自己的容器类型”的情况,拦截魔术方法会非常有帮助。为什么python不支持这种“拦截”?

aru*_*nte 5

对于完整的答案,您需要查看特殊方法查找文档,特别是:

除了为了正确性而绕过任何实例属性之外,隐式特殊方法查找通常也会绕过__getattribute__()甚至对象元类的方法。

理由如下:

__getattribute__()以这种方式绕过机制为解释器中的速度优化提供了很大的空间,代价是处理特殊方法的一些灵活性(特殊方法必须在类对象本身上设置,以便解释器始终如一地调用) .

请注意,这仅适用于新样式类(扩展的类object),但您确实应该始终对任何新代码使用新样式类。

最简单的解决方案是您需要手动代理所有您希望重定向到代理类的特殊方法。