Python - 选择要继承的 class

Python - Choose which class to inherit

我想制作两个 classes A 和 B,其中 B 是 A 的轻微但重要的变体,然后制作第三个 class C 可以继承 A或 B 并为它们添加功能。问题是,如何让C根据我的喜好继承A或B?

为了让事情更清楚,假设我有这段代码:

class A:

   def __init__(self, x, y):
       self.x = x
       self.y = y

   def first(self):
       return do_something(1)

   def second(self):
       return do_something(2)

   def third(self):
       return do_something(3)

   def start(self):
       self.first()
       self.second()
       self.third()

class B(A):

    def __init__(self, x, y, z):
        super().__init__(x, y)
        self.z = z

    def second(self):
        super().second()
        do_stuff()

    def third(self):
        do_other_stuff()

这是我使用的代码的一个非常简化的版本。特别地,A 代表制造系统的模拟器,而 B 代表同一制造系统的模拟器,但修改了主机床的行为。

现在,我想要的是添加代码来计算一些统计数据。它的作用是这样的:

class C(A):

    def __init__(self, *args):
        super().__init__(*args)
        self.stat = 0

    def second(self):
        super().second()
        self.stat += 1

    def third(self):
        super().third()
        self.stat *= 3

问题是 class C 的工作方式完全相同,无论是我继承 class A(如前面的清单)还是 class B(完全相同的代码,作为第一行 class C(B):

我该怎么做?还是我使用了一种不可行的方式?我认为一个理想的解决方案是在我初始化 C 时能够选择 class 继承 A 或 B。或者,也许,能够将 class 传递给 class C ]继承。

我做了一些研究,我也发现了聚合的可能性(我以前不知道),但我不认为它真的有用。最后一点,请注意 class A 可能有多达 20-30 个方法,当我使用 class C 时,我想要 class A(或 B,取决于它继承的)与以前一样工作,中间添加了 C 块。

P.S。我正在寻找一种可能优雅的、没有大量代码的 "pythonic" 方法来做到这一点。我也非常期待关于您认为可以做得更好的所有事情的建议。最后,我完全可以修改 class C,但是 class A 和 B 必须保持不变(除了小的改动)。

您可以使用新式classes及其方法解析顺序.

考虑这些定义:

class A(object):
    def __init__(self, x):
        pass

    def foo(self):
        print "A"

class B(object):
    def __init__(self, x, y):
        pass

    def foo(self):
        print "B"

您可以构建一个 mixin,旨在向 AB 添加功能:

class Cmix(object):
    def foo(self):
        super(Cmix, self).foo()
        print "mix"

并分别继承自 CmixA(或 B):

class CA(Cmix, A):
    pass

class CB(Cmix, B):
    pass

最后,你可以写一个方便的函数来根据参数的数量在CACB之间进行选择:

def C(*args):
    if len(args) == 1:
        return CA(*args)
    else:
        return CB(*args)

现在我们有

C(1).foo()
# A
# mix
C(1, 2).foo()
# B
# mix

请注意,C 不是真正的 class,例如,您不能将其用作 isinstance 中的第二个参数。