简体   繁体   English

为什么魔术方法不会被python中的__getattr__实现拦截?

[英]Why magic methods are not intercepted by __getattr__ implementation in python?

Subj. SUBJ。

Example: 例:

MyList(object):

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

    def __getattr__(self, item):
          return getattr(self._items, item)

Then 然后

MyList([1, 2, 3])[-1]

will raise: TypeError: 'MyList' object does not support indexing 将引发: TypeError: 'MyList' object does not support indexing

while: 而:

MyList([1, 2, 3]).pop()

will work perfectly ( pop will be intercepted by the __getattr__ and redirected to _items ) 将完美地工作( pop将被__getattr__拦截并重定向到_items

It seems for me that interception of magic methods by __getattr__ would be very helpful considering the case of "implementing own container types via composition not inheritance". 对我来说,考虑到“通过组合而不是继承实现自己的容器类型”的情况, __getattr__拦截魔术方法会非常有用。 Why is such "interception" not supported in python? 为什么python中不支持这样的“拦截”?

For the full answer, you need to look at the documentation for special method lookup , specifically: 要获得完整的答案,您需要查看特殊方法查找文档,特别是:

In addition to bypassing any instance attributes in the interest of correctness, implicit special method lookup generally also bypasses the __getattribute__() method even of the object's metaclass. 除了为了正确性而绕过任何实例属性之外,隐式特殊方法查找通常也会绕过__getattribute__()方法,甚至是对象的元类。

Which is justified by: 这是合理的:

Bypassing the __getattribute__() machinery in this fashion provides significant scope for speed optimisations within the interpreter, at the cost of some flexibility in the handling of special methods (the special method must be set on the class object itself in order to be consistently invoked by the interpreter). 以这种方式绕过__getattribute__()机制为解释器中的速度优化提供了很大的空间,代价是在处理特殊方法时有一定的灵活性(必须在类对象本身上设置特殊方法才能始终如一地调用翻译)。

Note that this only applies for new-style classes (classes which extend object ), but you really should always use new-style classes for any new code. 请注意,这仅适用于新式类(扩展object类),但实际上您应该始终对任何新代码使用新式类。

The simplest solution is that you need to manually proxy all of the special methods you wish to redirect to the proxy'd class. 最简单的解决方案是您需要手动代理您希望重定向到代理类的所有特殊方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM