How to Order Multiple Inheritance in Python, and What is the Order of Execution?
In Python, the order of multiple inheritance is controlled by the class definition and is determined by the Method Resolution Order (MRO).
How can you control the order of multiple inheritance in Python, and what determines the order in which methods are executed?
1. Defining the Inheritance Order
When you define a class with multiple parents, the order in which you list those parent classes determines the MRO. The first class listed is checked first when searching for methods.
class A:
def greet(self):
return "Hello from A"
class B(A):
def greet(self):
return "Hello from B"
class C(A):
def greet(self):
return "Hello from C"
class D(B, C): # B is checked before C
pass
d_instance = D()
print(d_instance.greet()) # Output: "Hello from B"
2. Understanding Method Resolution Order (MRO)
To see the MRO for any class, you can use the mro()
method or the __mro__
attribute:
print(D.mro()) # Output: [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
print(D.__mro__) # Same as above
The MRO indicates that:
- D checks B first,
- Then checks C,
- Then checks A,
- Finally checks the base class object.
3. Changing the Inheritance Order
If you want to prioritize a different class, simply change the order in which you list the parent classes in your definition.
class D(C, B): # Now C is checked before B
pass
d_instance = D()
print(d_instance.greet()) # Output: "Hello from C"
Summary of Execution Order
- First: Check the first parent class.
- Second: If the method isn’t found, check the next parent in the order.
- Continue: This continues down the MRO until a method is found or all classes are checked.
- Finally: If no method is found, Python raises an
AttributeError
.
Conclusion
By defining the order of parent classes in your class declaration, you control the MRO and thus the order of execution for methods in a multiple inheritance scenario.
Additonal
Example 1: Animal Classes
Imagine a scenario with different types of animals and their sounds.
class Animal:
def sound(self):
return "Some generic sound"
class Dog(Animal):
def sound(self):
return "Bark"
class Cat(Animal):
def sound(self):
return "Meow"
class Poodle(Dog):
def sound(self):
return "Woof"
class PersianCat(Cat):
def sound(self):
return "Purr"
class Pet(Poodle, PersianCat):
pass
pet = Pet()
print(pet.sound()) # Output: "Woof"
print(Pet.mro()) # Output: [<class '__main__.Pet'>, <class '__main__.Poodle'>, <class '__main__.PersianCat'>, <class '__main__.Cat'>, <class '__main__.Animal'>, <class 'object'>]
- When calling
pet.sound()
, Python first checksPoodle
(since it’s listed first), finds thesound
method there, and executes it. - The MRO shows the order in which Python checks for methods.
Example 2: Working with Vehicles
Consider a scenario involving different types of vehicles.
class Vehicle:
def drive(self):
return "Driving a vehicle"
class Car(Vehicle):
def drive(self):
return "Driving a car"
class Truck(Vehicle):
def drive(self):
return "Driving a truck"
class ElectricCar(Car):
def drive(self):
return "Driving an electric car"
class HybridTruck(Truck):
pass
class SuperTruck(HybridTruck, ElectricCar):
pass
super_truck = SuperTruck()
print(super_truck.drive()) # Output: "Driving a truck"
print(SuperTruck.mro()) # Output: [<class '__main__.SuperTruck'>, <class '__main__.HybridTruck'>, <class '__main__.Truck'>, <class '__main__.Vehicle'>, <class 'object'>]
- In this case,
SuperTruck
inherits fromHybridTruck
(which in turn inherits fromTruck
). The drive method fromTruck
is called because it's higher up the hierarchy compared toElectricCar
.
Example 3: Mixing Behaviors
Let’s create a scenario where we mix different behaviors using multiple inheritance.
class Swimmer:
def swim(self):
return "Swimming"
class Flyer:
def fly(self):
return "Flying"
class Duck(Swimmer, Flyer):
def quack(self):
return "Quack"
duck = Duck()
print(duck.swim()) # Output: "Swimming"
print(duck.fly()) # Output: "Flying"
print(duck.quack()) # Output: "Quack"
print(Duck.mro()) # Output: [<class '__main__.Duck'>, <class '__main__.Swimmer'>, <class '__main__.Flyer'>, <class 'object'>]
- Here,
Duck
inherits both swimming and flying behaviors fromSwimmer
andFlyer
. It showcases how multiple inheritance allows a class to combine functionalities from different classes.
Summary
These examples illustrate how multiple inheritance works in Python, how methods are resolved based on the MRO, and how you can effectively design your classes to leverage multiple inheritance for combining behaviors and functionalities.