Search code examples
pythonoopinheritancesuper

Using super() with multiple inheritance


The code is quite self-explanatory. I want to call both class A and class B __init__ methods.

Code:

class A(object):
    def __init__(self, name):
        self.name = name

class B(object):
    def __init__(self, age):
        self.age = age

class C(A, B):
    def __init__(self, name, age):
        A.__init__(self, name)
        B.__init__(self, age)


    def display(self):
        print(self.name, self.age)

c = C("xyz", 12)
c.display()

Output:

xyz 12

I want to use super() instead of explicitly stating

A.__init__(self, name)
B.__init__(self, age)

I am unable to find any resource for the same, need help.

The following does not work:

class A(object):
    def __init__(self, name):
        super(A, self).__init__()
        self.name = name

class B(object):
    def __init__(self, age):
        super(B, self).__init__()
        self.age = age

class C(A, B):
    def __init__(self, name, age):
        # A.__init__(self, name)
        # B.__init__(self, age)
        super(C, self).__init__(name, age)

    def display(self):
        print(self.name, self.age)

c = C("xyz", 12)
c.display()

Solution

  • When you create an instance of C, it's better if you pass keyword arguments so that you know which is which. Positional arguments work too but with keyword arguments, you don't have to worry about messing up the order of arguments.

    Then since C defers the definition of self.name and self.age to parent classes, you immediately pass all arguments up the heirarchy using super().__init__(**kwargs). The best thing about inheritance is that child classes don't even need to know about the parameters it doesn't handle. The first parent class is A, so self.name is defined there. The next parent class in the method resolution order is B, so from A, you pass the remaining keyword arguments to B, using super().__init__(**kwargs) yet again.

    class A(object):
        def __init__(self, name, **kwargs):
            self.name = name
            super().__init__(**kwargs)
    
    class B(object):
        def __init__(self, age, **kwargs):
            self.age = age
            super().__init__(**kwargs)    # this is actually not needed but in case you have other base classes after B, might come in handy
    
    class C(A,B):
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
    
        def display(self):
            print(self.name, self.age)
    
    c = C(name="xyz",age=12)
    c.display()
    

    Output:

    xyz 12