Inheritance vs. Composition in Python for this specific case?
<p>Assume I have a series of classes as follows:
</p>

<pre><code>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
</code></pre>

<p>If now D is a both B and C, it can be implemented as
</p>

<pre><code>class D(B,C)
    __init__(self,a,b,c1,c2,d):
        pass
</code></pre>

<p>Or <code>D</code> can be understood as a combination of <code>B</code> and <code>C</code>
</p>

<pre><code>class D(B,C)
    __init__(self,a,b,c1,c2,d):
        self.b=B(a,b)
        self.c=C(a,c)
</code></pre>

<p>which seems a bit more complicated than the multi-inheritance case.</p>

<p>Well, Now let's imaging <code>class D2</code> is a combination of 5 pieces of <code>B</code> and 3 pieces of <code>C</code>, and <code>class D3</code> is made of <code>D2</code> plus an additional <code>C</code>(with different parameter than the ones in <code>D</code>), and <code>D4</code> is made of <code>D2</code> and 2 additional pieces of <code>C</code>(these 2 additional <code>C</code> has same parameter but different from the ones in <code>D2</code>). It seems <code>D2</code> is good to use composition, but <code>D3</code> is good to use inheritance of <code>D2</code> and <code>C</code>, and <code>D4</code> is good to use inheritance of <code>D2</code> and <code>C</code>. </p>

<p>Use combinations, to me, has the disadvantage that I have to write <code>d.c.c1</code> rather than <code>d.c1</code>(as in inheritance case)to get the parameter <code>c</code> or I need to store the parameter <code>c</code> in D directly(besides the one as <code>d.c.c1</code>). Is there any philosophical consistent way to deal with these classes? Thanks!</p>

<p>You're bound to get some level of opinion on a question like this -- My answer is to use inheritance <em>iff</em> your classes are designed to be inherited.  Use composition in all the other cases.  In practice, this usually means that if the code that you are extending exists in a realm out of your control, don't subclass it unless their documentation talks about <em>how</em> you can subclass it effectively.</p>

<p>In this case, since it seems like you are the author of the class hierarchy, inheritance seems to make sense (though some of your assertions are incorrect -- <code>D</code> is not so easy to implement as you have supposed since none of the superclass <code>__init__</code> will get called).  You probably should familiarize yourself with the design pattern in Raymond Hettinger's <a href="https://rhettinger.wordpress.com/2011/05/26/super-considered-super/" rel="nofollow">"super considered super" article</a></p>

<pre><code>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
</code></pre>

<p><em>now</em> the implementation of <code>D</code> is trivially simple:</p>

<pre><code>class D(B, C):
    pass
</code></pre>

<p>Note that we don't even need to define <code>__init__</code> because all of the constructors of the super classes can accept arbitrary keyword arguments.  Instantiating a <code>D</code> looks like:</p>

<pre><code>d = D(a='a', b='b', c1='c1', c2='c2')
</code></pre>

python inheritance combinations