覆盖数字魔法作为classmethod
我尝试使用Metaclass为几个类实现数字魔法方法,然后在“类实例”中覆盖其中的一些方法。
from abc import ABCMeta
class Meta(ABCMeta):
def __add__(self, other):
print('meta')
class C(metaclass=Meta):
@classmethod
def __add__(cls, other):
print('C')
C + 3 # meta
C.__add__(3) # C
它表明+
操作员与Meta
's __添加__
直接调用,但c。 > getAttr(c,'__ADD __')
并正确使用Overriden类方法。
我尝试了几个代码来确认这一点。
class Meta(ABCMeta):
def call(self):
print('meta')
class C(metaclass=Meta):
@classmethod
def call(cls):
print('C')
C.call() # C
class C:
@classmethod
def __add__(cls, other):
print('C')
C + 3 # TypeError
C.__add__(3) # C
我猜我“注册”我对__添加__
的暗示时会发生一些特殊的事情,因此Decorator @ClassMethod
不起作用。
那么,Python如何评估c + 3
的表达式?如果我想覆盖__添加__
c
,除了从meta
继承其他元口外,还有其他解决方案吗?
I try to use metaclass to implement numeric magic methods for several classes, then override some of them in the "class instance".
from abc import ABCMeta
class Meta(ABCMeta):
def __add__(self, other):
print('meta')
class C(metaclass=Meta):
@classmethod
def __add__(cls, other):
print('C')
C + 3 # meta
C.__add__(3) # C
It shows that the +
operator is directly called with Meta
's __add__
, but C.__add__
calls getattr(C, '__add__')
and correctly use the overriden class method.
I've tried several code pieces to confirm that.
class Meta(ABCMeta):
def call(self):
print('meta')
class C(metaclass=Meta):
@classmethod
def call(cls):
print('C')
C.call() # C
class C:
@classmethod
def __add__(cls, other):
print('C')
C + 3 # TypeError
C.__add__(3) # C
I guess something special happends when I "register" my implmentation of __add__
, so the decorator @classmethod
does not work.
So, how does python evaluates the expression C + 3
? If I want to override __add__
for C
, is there any solution other than inherit another metaclass from Meta
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这里发生的是Python的方法和属性搜索优先级不同于普通方法(例如
call
),以及通过使用操作员(例如__添加__
),以后,Python直接将添加到添加实例类的插槽中。也就是说:当您将“ C”与
+
运算符一起使用时,其类是“元”,meta .__添加__
被调用。在普通属性中,使用
。
符号(c.call
,甚至c .__添加__
(使用+),属性访问的正常规则 - 遵循
对象中实现的。 /70590552/hy-do-getting-a级 - 阶级 - 统计 - and-instance-raise-an-attributeError/70593783#70593783>这个答案。但简而言之:对于虚线访问,在“ class'Class”中定义的方法之前检索了类“实例”中的类别(就像
__ dict dict of the a a a a a a a class'class''普通实例“与同类中的相同属性相比)。
至于:“如果我想覆盖
__添加__
,除了从Meta继承另一个Metaclass外,还有其他解决方案吗?”“显而易见的方法”是为每个类别提供一个单独的元素,您要实现“类
__添加__
”的方法。但是,您可以编写meta。它。
What takes place here is that Python's method and attribute search priority are different from ordinary methods (like
call
), and methods that are intended to be called indirectly by the language, through the use of an operator (like__add__
)For the later, Python defers directly to the slot in the class of the instance being added. That is: When you use "C" with the
+
operator, its class is "Meta", andMeta.__add__
is called.In an ordinary attribute access using the
.
notation (eitherC.call
or evenC.__add__
(insteaf of using+
)), the normal rules for attribute access - which are implemented inobject.__getattribute__
are followed - I've summarized the precedence in this answer. But in short: for dotted access, the classmethod in the class "instance" is retrieved before the method defined in the "class'class" (just as would happen for an attribute in the__dict__
of an "ordinary instance" compared to the same attribute in its class).As for: "If I want to override
__add__
for C, is there any solution other than inherit another metaclass from Meta?"The "obvious way" would be to have a separate metaclass for each class you want to implement a "class
__add__
" method to. However, you can writeMeta.__add__
so that it, upon being called, check for the existence of an__add__
method in the class, and forwards the execution of the opertation to it.