Python 中针对此特定情况的继承与组合?

Inheritance vs. Composition in Python for this specific case?

假设我有一系列 类 如下:

class A(object):
    __init__(self,a):
        self.a=a
class B(A):
    __init__(self,a,b):
        super(B,self).__init__(a)
        self.b=b
class C(A):
    __init__(self,a,c1,c2):
        super(C,self).__init__(a)
        self.c1=c1
        self.c2=c2

如果现在D既是B又是C,它可以实现为

class D(B,C)
    __init__(self,a,b,c1,c2,d):
        pass

或者D可以理解为BC的组合

class D(B,C)
    __init__(self,a,b,c1,c2,d):
        self.b=B(a,b)
        self.c=C(a,c)

这似乎比多重继承的情况要复杂一些。

好吧,现在让我们想象一下class D2是5个B和3个C的组合,而class D3是由[=21=组成的]加上一个额外的C(与D中的参数不同),D4D2和2个额外的C组成(这些2 个额外的 C 具有相同的参数,但与 D2 中的不同。好像D2好用组合,但是D3好用D2C的继承,D4好用[的继承=21=] 和 C

对我来说,使用组合的缺点是我必须写 d.c.c1 而不是 d.c1(在继承情况下)来获取参数 c 或者我需要将参数c直接存入D(d.c.c1除外)。有什么哲学上一致的方法来处理这些类?谢谢!

您一定会对这样的问题获得某种程度的意见 -- 我的答案是使用继承 iff​​ 您的 classes 被设计为遗传。在所有其他情况下使用组合。实际上,这通常意味着如果您要扩展的代码存在于您无法控制的领域,请不要将其子class,除非他们的文档谈到如何您可以有效地subclass它。

在这种情况下,由于您似乎是 class 层次结构的作者,继承似乎是有道理的(尽管您的某些断言不正确 - D 并不那么容易按照您的设想实施,因为 superclass __init__ 的 none 将被调用)。您可能应该熟悉 Raymond Hettinger "super considered super" article

中的设计模式
class A(object):
    def __init__(self, a, **kwargs):
        super(A, self).__init__(**kwargs)
        self.a = a

class B(A):
    def __init__(self, b, **kwargs):
        super(B, self).__init__(**kwargs)
        self.b = b

class C(A):
    def __init__(self, c1, c2, **kwargs):
        super(c, self).__init__(**kwargs)
        self.c1 = c1
        self.c2 = c2

现在 D 的实现非常简单:

class D(B, C):
    pass

请注意,我们甚至不需要定义 __init__,因为所有超 classes 的构造函数都可以接受任意关键字参数。实例化一个 D 看起来像:

d = D(a='a', b='b', c1='c1', c2='c2')