If you’re just starting to learn about Python, or if you’re already familiar with it, you’ve probably heard about “inheritance.” Inheritance is a powerful feature of object-oriented programming that allows us to create new classes based on existing ones.
In Python, understanding inheritance is especially important because it can help us write more efficient, organized, and maintainable code.
In this article, I’ll be introducing you to the different types of inheritance in Python. We’ll explore single, multiple, multi-level, hierarchical, and hybrid inheritance, and I’ll give you examples of each type to help you understand how they work.
We’ll also talk about Method Resolution Order (MRO), which is how Python determines the order in which it looks for methods and attributes in inheritance hierarchies. By the end of this article, you’ll have a solid understanding of the different types of inheritance in Python, and you’ll be able to choose the right type of inheritance for your projects.
So, let’s dive in!
Single Inheritance
Single inheritance is the simplest type of inheritance in Python. It allows us to create a new class that inherits the attributes and methods of a single existing class. This existing class is called the “parent” or “base” class, and the new class we create is called the “child” or “derived” class.
To create a child class using single inheritance, we use the syntax “class ChildClass(ParentClass)
.” This tells Python that we want to create a new class that inherits from the ParentClass
. We can then define new methods and attributes in the child class that are specific to our needs.
Here’s an example of how we could use single inheritance in Python:
class Animal:
def __init__(self, name, species):
self.name = name
self.species = species
def make_sound(self):
print("Some generic animal sound.")
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name, species="Canine")
self.breed = breed
def make_sound(self):
print("Woof!")
In this example, we define a base class called “Animal
” that has an init() method and a make_sound()
method.
We then define a child class called “Dog
” that inherits from Animal
. In the Dog
class, we define an init()
method that calls the init()
method of the Animal
class using the “super()
” function. We also define a new attribute called “breed
” and a new implementation of the make_sound()
method specific to dogs.
When we create an instance of the Dog
class and call its methods, we can see that it inherits the name and species attributes from the Animal
class, but has its implementation of the make_sound()
method.
Multiple Inheritance
Multiple inheritance is a more complex type of inheritance in Python that allows us to create a new class that inherits from multiple existing classes. This means the new class will have attributes and methods from all its parent classes. This can be useful when we want to combine the functionality of multiple classes into one.
To create a child class using multiple inheritance, we use the syntax “class ChildClass(ParentClass1, ParentClass2, …):”. This tells Python that we want to create a new class that inherits from multiple parent classes. We can then define new methods and attributes in the child class that are specific to our needs.
Here’s an example of how we could use multiple inheritance in Python:
class Vehicle:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
def start(self):
print("Starting vehicle...")
class Electric:
def __init__(self, battery_level):
self.battery_level = battery_level
def charge(self):
print("Charging battery...")
class ElectricCar(Vehicle, Electric):
def __init__(self, make, model, year, battery_level):
Vehicle.__init__(self, make, model, year)
Electric.__init__(self, battery_level)
def start(self):
print("Starting electric car...")
In this example, we define a base class called “Vehicle
” that has an init()
method and a start()
method. There is a base class called “Electric
” that has an init()
method and a charge()
method. We then define a child class called “ElectricCar
” that inherits from both Vehicle and Electric.
In the ElectricCar
class, we define an init()
method that calls the init()
methods of both Vehicle
and Electric
. We also define a new implementation of the start()
method specific to electric cars.
When we create an instance of the ElectricCar
class and call its methods, we can see that it inherits the make, model, and year attributes from the Vehicle
class, the battery_level attribute and charge() method from the Electric class. We can also see that it has its implementation of the start()
method.
Related: Difference Between List, Tuple, Set, and Dictionary in Python
Multi-Level Inheritance
Multi-level inheritance in Python allows us to create a new class that inherits from a child class, which itself inherits from a parent class. This means that the new class will have attributes and methods from both the child and parent classes and any other ancestor classes in the hierarchy.
To create a child class using multi-level inheritance, we define a new class that inherits from the child class. We can then define new methods and attributes in the child class that is specific to our needs.
Here’s an example of how we could use multi-level inheritance in Python:
class Animal:
def __init__(self, name, species):
self.name = name
self.species = species
def make_sound(self):
print("Some generic animal sound.")
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name, species="Canine")
self.breed = breed
def make_sound(self):
print("Woof!")
class Corgi(Dog):
def __init__(self, name):
super().__init__(name, breed="Corgi")
def make_sound(self):
print("Yip!")
In this example, we define a base class called “Animal
” that has an init()
method and a make_sound()
method. There is a child class called “Dog
” that inherits from Animal
and adds a new attribute called “breed
” and a new implementation of the make_sound()
method.
There is a child class called “Corgi
” that inherits from Dog
and adds no new attributes but changes the implementation of the make_sound()
method.
When we create an instance of the Corgi
class and call its methods, we can see that it inherits the name, species, and breed attributes from the Dog class, which in turn inherits the name and species attributes from the Animal class. We can also see that it has its implementation of the make_sound()
method.
Hierarchical Inheritance
Hierarchical inheritance is a type of inheritance in Python where a child class inherits from a single parent class, but multiple child classes inherit from the same parent class. This means that each child class will have attributes and methods from the parent class, but they may have different implementations of those methods or additional methods and attributes specific to their needs.
We define new classes inherited from the same parent class to create child classes using hierarchical inheritance. We can then define new methods and attributes in each child class specific to their needs.
Here’s an example of how we could use hierarchical inheritance in Python:
class Animal:
def __init__(self, name, species):
self.name = name
self.species = species
def make_sound(self):
print("Some generic animal sound.")
class Cow(Animal):
def __init__(self, name, breed):
super().__init__(name, species="Taurus")
self.breed = breed
def make_sound(self):
print("Moo!")
class Lion(Animal):
def __init__(self, name):
super().__init__(name, species="Lion")
def roar(self):
print("ROAR!!!")
In this example, we define a base class called “Animal
” that has an init()
method and a make_sound()
method. There is a child class called “Cow
” that inherits from Animal
and adds a new attribute called “breed
” and a new implementation of the make_sound()
method.
There is another child class called “Lion
” that inherits from Animal
and adds a new method called “roar
“.
When we create instances of the Cow
and Lion
classes and call their methods, we can see that they both inherit the name and species attributes from the Animal
class, but they have their implementations of the make_sound()
and roar()
methods, respectively.
We can also see that the Cow
class has an additional breed
attribute that the Lion
class does not have.
Hybrid Inheritance
Hybrid Inheritance is a combination of two or more types of inheritance in a single class hierarchy. It involves the use of multiple inheritance, where a class can inherit from more than one parent class, as well as other types of inheritance such as multi-level or hierarchical inheritance.
To illustrate Hybrid Inheritance, let’s consider an example where we have three classes: Animal, Bird, and Parrot. The Animal class defines basic properties and methods that all animals have, the Bird class defines properties and methods specific to birds, and the Parrot class is a hybrid of both the Animal and Bird classes.
Here is an example code:
class Animal:
def __init__(self, name, age, sound):
self.name = name
self.age = age
self.sound = sound
def get_info(self):
return f"{self.name} is {self.age} years old and makes the sound {self.sound}."
class Bird:
def __init__(self, wingspan):
self.wingspan = wingspan
def fly(self):
return "I'm flying!"
class Parrot(Bird, Animal):
def __init__(self, name, age, sound, wingspan, hair_color):
super().__init__(wingspan)
self.hair_color = hair_color
Animal.__init__(self, name, age, sound)
def speak(self):
return "Polly wants a cracker!"
In this example, the Parrot
class inherits from both the Bird
and Animal
classes, and also includes its own properties and methods such as the hair_color
attribute and the speak()
method.
When we create a new Parrot
object with the name “Polly”, age 2, sound “Squawk”, wingspan 12, and hair color “Green,” we can call methods on this object.
In this way, we can use Hybrid Inheritance to create complex class hierarchies that combine the properties and methods of multiple parent classes, while still allowing us to customize our own attributes and behaviors.
Method Resolution Order (MRO)
Method Resolution Order (MRO) is the order in which Python looks for methods and attributes in a class hierarchy. When we define a class that inherits from one or more parent classes, Python needs to determine the order in which it should search for a particular method or attribute when we call it on an object of that class.
To determine the MRO, Python uses a special algorithm called the C3 algorithm, which takes into account the order in which the parent classes are listed in the child class definition and the MROs of the parent classes themselves.
When we call a method on an object of a class, Python looks for that method in the class itself. If not found there, Python then looks for the method in the first parent class listed in the child class definition. If it’s not found there, Python then looks for the method in the second parent class listed in the child class definition, and so on, until it either finds the method or reaches the end of the MRO.
If a method is defined in multiple parent classes, Python will use the MRO to determine which version of the method to use. This can be important in multiple or hybrid inheritance cases, where two or more parent classes define the same method but with different implementations.
We can view the MRO of a class using the built-in method “mro()”. For example, if we have a class called “MyClass” that inherits from two parent classes “Parent1” and “Parent2”, we can view its MRO by calling “MyClass.mro()”.
Here’s an example to illustrate how MRO works in Python:
In this example, we define a class hierarchy with four classes: A, B, C, and D. Class B and C both inherit from class A, and class D inherits from both class B and class C using multiple inheritance.
When we create an instance of class D and call the method “my_method()”, Python looks for the method in class D first. Since it’s not defined there, Python looks for the method in class B, which inherits from class A.
Again, it’s not defined there, so Python looks for the method in class C, which overrides the implementation of the method defined in class A. Python finds the implementation of the method in class C and calls it, which results in the output “C”.
If we view the MRO of class D using the “mro()” method, we can see that it starts with class D, then goes to class B (since it was listed first in the class definition), then goes to class C (since it was listed second in the class definition), then goes to class A, and finally goes to the built-in “object” class.
This is the order in which Python searches for methods and attributes in the class hierarchy.
Conclusion
Understanding the different types of inheritance in Python is essential for creating efficient and organized code. By utilizing inheritance, we can reuse code from existing classes, reducing the amount of code we need to write and improving the overall structure of our programs.
In Python, we have five different types of inheritance: single, multiple, multi-level, hierarchical, and hybrid. Each type of inheritance has its own unique features and advantages, and knowing when and how to use each one can help us write more flexible and maintainable code.
In addition, we also learned about the Method Resolution Order (MRO) and how it determines the order in which Python searches for methods and attributes in a class hierarchy.
By mastering inheritance and understanding the MRO, we can write more efficient, scalable, and maintainable Python code.