重用Python中多个类之一的继承树

问题描述 投票:0回答:1

我有 2 个类,每个类都实现特定行为并使用父类。

现在我有一个新类需要使用任一行为,但只能在构造期间/之后确定哪一个行为。

目前这是通过使用多重继承来完成的。 然而,由于基类的编写并未考虑到这一点,因此包含的

super()
调用将调用错误的子树

考虑以下 MWE:

class A:
    def __init__(self, use_b):
        self.init_b = use_b  # Maybe complicated

    def foo(self):
        print("A")


class B(A):
    def foo(self):
        super().foo()
        print("B")


class C1(A):
    def foo(self):
        super().foo()
        print("C1")


class C2(C1):
    def foo(self):
        super().foo()
        print("C2")


class D(B, C2):
    def __init__(self, *args):
        super().__init__(*args)
        self.use_b = self.init_b

    def foo(self):
        if self.use_b:
            B.foo(self)
        else:
            C2.foo(self)

d = D(True)
d.foo()

print("NEXT")
d = D(False)
d.foo()

A
中的某个位置初始化了一个属性,该属性在
D
中使用来确定要使用的适当类。两个候选者
B
C2
都继承自基类,因为它们现在/曾经是独立的实现

它适用于调用

C2.foo
,但调用
B.foo
最终会在
foo
C2
中调用
C1
,这是我不想要的。

我确实知道为什么会发生这种情况(MRO),但没有好主意来解决这个问题。

我也许可以让

D
仅继承于
A
,初始化它,然后决定使用哪个子类,即:

class D(A):
    def __init__(self, *args):
        super().__init__(*args)
        if self.init_b:
            self.impl = B(*args)
        else:
            self.impl = C2(*args)

    def foo(self):
        self.impl.foo()

但这有3个问题:

  1. 它至少初始化
    A
    多次。这对性能不利,如果
    A.__init__
    修改引用类型参数(例如列表),可能会失败
  2. 如果只有一些参数
    B
    C2
    理解,那么
    A
    无法处理它们,它可能会失败
  3. 我需要实现并包装可以调用的 A
    all
    方法。如果我忘记了被
    B
    C
    类覆盖的一个,则行为将默默地错误。类似的属性

有没有一种干净、安全的方法来处理这种情况?

python inheritance overloading multiple-inheritance method-resolution-order
1个回答
0
投票

您需要使用

super
的可选参数:

class D(B, C2):
    def __init__(self, *args):
        super().__init__(*args)
        self.use_b = self.init_b

    def foo(self):
        if self.use_b:
            super(B, self).foo()
        else:
            super(C2, self).foo()
© www.soinside.com 2019 - 2024. All rights reserved.