Search code examples
pythonpython-3.xooppython-2.xmultiple-inheritance

Python: Calling multiple inits in Multiple inheritance


I have 2 classes: A (which needs 1 argument to initialize) and B (which needs 2 arguments to initialize), and a third class C which derives from both A and B.

class A:
    def __init__(self, sval): 
        print("A: rcd value: ", sval)
        self.aval = sval

class B: 
    def __init__(self, sval, tval):
        print("B: rcd 2 values: ", sval, tval)
        self.aval=sval
        self.bval=tval

class C(A,B):
    def __init__(self, a, b, c):
        super().__init__(a) 
        super().__init__(b,c) # error here

c = C(1,2,3)

When I run above code, there is error at the last line; __init__ of class A is called, not that of class B.

A: rcd value:  1
Traceback (most recent call last):
  File "inheritance.py", line 20, in <module>
    c = C(1,2,3)
  File "inheritance.py", line 16, in __init__
    super().__init__(b,c) 
TypeError: __init__() takes 2 positional arguments but 3 were given

How can I call __init__ functions of both A and B from __init__ of class C?

Edit: I am using Python 3.5.3 on Debian Linux, though I will prefer a solution which works on both Python2 and Python3.


Solution

  • Let's assume you have control over A and B and can avoid using the same attribute name in both. Then in order to correctly use super, define them as follows.

    class A:
        def __init__(self, aval, **kwargs): 
            print("A: rcd value: ", aval)
            self.aval = sval
            super().__init__(**kwargs)
    
    class B: 
        def __init__(self, b1val, b2val, **kwargs):
            print("B: rcd 2 values: ", b1val, b2val)
            self.b1val = b1val
            self.b2val = b2val
            super().__init__(**kwargs)
    

    Then C.__init__ needs to call super only once:

    class C(A, B):
        def __init__(self, aval, b1val, b2val, **kwargs):
            super().__init__(aval=aval, b1val=b1val, b2val=b2val, **kwargs)
    
    c = C(1, 2, 3)