1

Say I have a class called Vehicle, and I have two sub classes called Boat and Car, which inherit from Vehicle.

Now say I have an amphibious vehicle, which uses multiple inheritance AmphibiousVehicle(Boat, Car).

Now my question is: how should the __init__ function of AmphibiousVehicle be defined?

Both Boat and Car initialize Vehicle with a call to super().__init__().

Do I need to initialize Boat and Car one by one in the init of AmphibiousVehicle?

Or can I just call super once? If I do that, I don't see how Car gets initialized?

1 Answer 1

2

Python uses cooperative multiple inheritance. That means that your call to super() doesn't necessarily hit the base class of where it's called, it hits the next class in the method resolution order (MRO) from where you started.

To demonstrate:

class A:
    def __init__(self):
        print("A.__init__")
        super().__init__()

class B:
    def __init__(self):
        print("B.__init__")
        super().__init__()

class C(A, B):
    def __init__(self):
        print("C.__init__")
        super().__init__()

c = C()

Gives the output:

C.__init__
A.__init__
B.__init__

So the call super().__init__() inside class A calls __init__() in class B, even though class A does not inherit from class B.

So long as all your classes make sure they call super where appropriate, you only need to call it once and trust that everything will cooperate.

The MRO is basically the order in which python will search the classes for a method or attribute. You can examine what this order is by inspecting the __mro__ attribute on a class:

print(C.__mro__)

Gives us:

(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
Sign up to request clarification or add additional context in comments.

6 Comments

But what if both A, B themselves inherit from AA, BB (and in my case AA = BB)? Then when will their inits get called?
If both A and B inherit from AA, the MRO would be C->A->B->AA (and then ->object, implicitly). You can query what the MRO is by examining the __mro__ attribute on a class.
@sakuew2 if both Car and Boat call super().__init__ in their init, init of Vehicle will be called. Because, when they call super.init, AmphibiousVehicle calls Car.init which calls Boat.init which then calls Vehicle.init
Yes, exactly, so long as they all call super.__init__()
Okay, but here's what I don't understand. You say Boat.init calls Vehicle.init. But that means Car.init does NOT call Vehicle.init. That means that there may be a method IN Car that calls a method in Vehicle. So what happens? Is that method automatically deferred to `Boat' and THEN to Vehicle?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.