Mixin 覆盖继承的方法

Mar*_*ilk 4 python inheritance multiple-inheritance mixins

我有一个类的集合,A1、A2、A3 等,它们都有方法m()。我也有带方法的 B 类m()。我希望能够轻松创建m()从类 B调用的类 C1、C2、C3 等,同时还具有 A1、A2、A3 等的所有其他属性...

但是,我遇到的问题是,在类 C1 中m(),类 B 中的方法应该m()从类 A1 中调用。

我很难用语言表达我想要的东西,但我目前正在考虑这样做的方式是使用 mixins。C1 将从 A1 继承,并混入 B。但是,我不知道如何m()在 B 中m()从 A 类之一中调用正确的。

所以,我的两个问题:

  • 我正在尝试做的事情有名字吗?
  • 这样做的正确方法是什么?

编辑:根据要求,一个具体的例子:m(p)A1、A2、A3 等中的方法都计算矩阵M,对于某些参数p。我想创建类 C1、C2、C3 等,它们的行为方式与 A1、A2、A3 相同,除了method m()。新方法m()需要一个更长的参数列表p,大小为 N,我们计算A*.m()N 次,然后返回总和。

用于计算m()所有 A* 类的总和的代码是相同的。在上面建议的混合解决方案中,求和代码将在 B 中。 B 和 A1 都将被继承以形成 C1。然而,该方法m()C1从B将不得不调用A1.m()

MSe*_*ert 6

我认为您只需super要将调用重定向到父类或兄弟类(取决于 MRO)。

例如:

class A1(object):
    def m(self):
        print('Calling method m of class A1')
        self.data *= 2

class A2(object):
    def m(self):
        print('Calling method m of class A2')
        self.data *= 3

class A3(object):
    def m(self):
        print('Calling method m of class A3')
        self.data *= 4

class B(object):
    def m(self, p):
        print('Calling method m of class B')
        for i in range(p):
            # You haven't specified which python you are using so I assume
            # you might need to most explicit variant of super().
            # Python3 also allows just using super().m()
            super(B, self).m()

class C1(B, A1):
    def __init__(self, value):
        self.data = value
Run Code Online (Sandbox Code Playgroud)

只是测试一下:

a = C1(10)
a.m(10)
Run Code Online (Sandbox Code Playgroud)

印刷:

Calling method m of class B
Calling method m of class A1
Calling method m of class A1
Calling method m of class A1
Calling method m of class A1
Calling method m of class A1
Calling method m of class A1
Calling method m of class A1
Calling method m of class A1
Calling method m of class A1
Calling method m of class A1
Run Code Online (Sandbox Code Playgroud)

和保存的值:

a.data
# returns 10485760
Run Code Online (Sandbox Code Playgroud)

也定义其他C作品:

class C2(B, A2):
    def __init__(self, value):
        self.data = value

a = C2(10).m(2)
#Calling method m of class B
#Calling method m of class A2
#Calling method m of class A2


class C3(B, A3):
    def __init__(self, value):
        self.data = value

a = C3(10).m(1)
#Calling method m of class B
#Calling method m of class A3
Run Code Online (Sandbox Code Playgroud)

当然,您需要另一种逻辑,并且可能需要从中返回值.m()而不是就地修改,但我认为您可以自己解决。

您要查找的词可能是MRO (method resolution order)。希望这对你有帮助。

同样感兴趣的可能是super(Python2) , super(Python3)的文档。

并且您始终可以MRO通过调用该.mro()方法来检查类的:

print(C1.mro())
[<class '__main__.C1'>, <class '__main__.B'>, <class '__main__.A1'>, <class 'object'>]
Run Code Online (Sandbox Code Playgroud)

所以python首先检查是否C1有方法m,如果没有则检查BB有一个所以它被执行。然后super调用再次进入MRO并检查下一个类 ( A1) 是否有方法m,然后执行该方法。

  • 您可能想澄清一下 `super()` 并不总是调用父级,它会在 MRO* 的下一个类中查找请求的属性。在这种情况下,它可以找到一个兄弟类。 (2认同)