针对Python的Walk MRO特殊方法未实现

针对Python的Walk MRO特殊方法未实现,python,oop,multiple-inheritance,method-resolution-order,Python,Oop,Multiple Inheritance,Method Resolution Order,我有一个代数对象类的层次结构,这些代数对象实现了特殊的方法,如\uuuu mul\uuu和\uuuu add\uuuu,并使用多重继承。我在某种程度上假设Python(>=3.5)将按照方法解析顺序(mro)查找第一个不返回NotImplemented的方法。唉,情况似乎并非如此。考虑下面的最小例子: class A(): def __mul__(self, other): return "A * %s" % other class B(): def __mul

我有一个代数对象类的层次结构,这些代数对象实现了特殊的方法,如
\uuuu mul\uuu
\uuuu add\uuuu
,并使用多重继承。我在某种程度上假设Python(>=3.5)将按照方法解析顺序(mro)查找第一个不返回
NotImplemented
的方法。唉,情况似乎并非如此。考虑下面的最小例子:

class A():
    def __mul__(self, other):
        return "A * %s" % other

class B():
    def __mul__(self, other):
        if isinstance(other, int):
            return "B * %s" % other
        else:
            return NotImplemented

class C(B, A):
    pass

class D(B, A):
    def __mul__(self, other):
        res = B.__mul__(self, other)
        if res is NotImplemented:
            res = A.__mul__(self, other)
        return res
在这段代码中,我用所需的行为实现了
D

>>> d = D()
>>> d * 1
'B * 1'
>>> d * "x"
'A * x'
然而,我实际上希望
C
的行为与
D
相同,但它没有:

>>> c = C()
>>> c * 1
'B * 1'
>>> c * "x"
Traceback (most recent call last):
File "<ipython-input-23-549ffa5b5ffb>", line 1, in <module>
    c * "x"
TypeError: can't multiply sequence by non-int of type 'C'
>c=c()
>>>c*1
“B*1”
>>>c*“x”
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
c*“x”
TypeError:无法将序列与类型为“C”的非整数相乘
当然,我知道发生了什么:我只是返回mro中第一个匹配方法的结果(我只是希望
NotImplemented
将作为一个特殊值处理)


我的问题是,是否有任何方法可以绕过编写类似
D.\uuuuu mul\uuuuu
的样板代码(对于所有的数值特殊方法,对于所有的类,这基本上是相同的)。我想我可以编写一个类装饰器或元类来自动生成所有这些方法,但我希望有一种更简单的(标准库)方法,或者,有人已经做了类似的事情。

Python在您要求它时向MRO走去,不意味着要保持更高的检查级别。将您的代码更改为与
super()
(向上引导MRO到下一个类的请求)一起使用协作继承,否则您将返回
NotImplemented
,它应该可以工作。它完全不需要
C
D
来定义
\uuuuuuuuuuuuuu
,因为它们不向其功能添加任何内容:

class A():
    def __mul__(self, other):
        return "A * %s" % other

class B():
    def __mul__(self, other):
        if isinstance(other, int):
            return "B * %s" % other
        try:
            return super().__mul__(other)  # Delegate to next class in MRO
        except AttributeError:
            return NotImplemented  # If no other class to delegate to, NotImplemented

class C(B, A):
    pass

class D(B, A):
    pass  # Look ma, no __mul__!
然后测试:

>>> d = D()
>>> d * 1
'B * 1'
>>> d * 'x'
'A * x'
super()
的神奇之处在于,它即使在多重继承场景中也能工作,在这种情况下,一个类
B
A
一无所知,但如果一个子类恰好从这两个类继承,它仍然会愉快地委托给它(或任何其他可用的类)。如果没有,我们将处理结果的
AttributeError
,使结果
不实现
,就像以前一样,因此类似这样的东西按预期工作(它尝试
str
\uu rmul
不识别非
int
并分解):


是的,就是这样!一旦你看到它,它就非常有意义!
>>> class E(B): pass
>>> e = E()
>>> e * 1
'B * 1'
>>> e * 'x'
Traceback (most recent call last)
...
TypeError: can't multiply sequence by non-int of type 'E'