inheritance-blog.png

Inheritance In Python

Last Updated | Jan, 13, 2021 By Kingsley Ijomah
Inheritance is a powerful feature in object-oriented programming, in this post we will learn how to use inheritance in Python, we will also learn about single and multiple inheritance as well as method resolution order (MRO).
inheritance-pinterest2.png

What is inheritance in Python

Inheritance is a powerful feature in object-oriented programming. It allows us to create a child/subclass which inherits all methods and properties from a parent/superclass.

To understand inheritance you need to be familiar with classes and objects: what are classes and objects in python

Python Inheritance Syntax:

code
# Inheritance syntax
class SuperClass:
  #Body of super class
class SubClass(SuperClass):
  #Body of subclass class

Super and subclass in Python

Below is an example of a super Animal and subclass Dog which inherits the speak() method from Animal class

code
class Animal:
    """A class used to represent an animal"""

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def speak(self):
        return f"My name is {self.name} and I am {self.age} years old!"


class Dog(Animal):
    """A class used to represent a dog"""
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.type = "dog"


fufu = Dog(name="fufu", age=2)
print(fufu.speak()) #ouput: My name is fufu and I am 2 years old!

As you can see from above, we are able to call speak() method on the dog object even though there is no speak() method in the dog class.

The super method in Python

super() gives you access to methods in the superclass from the subclass. super() on its own returns a temporary object of the superclass that allows you to call the superclass's methods.

code
'''
Notice how we use super() to call the super class's __init__
method.
'''
class Dog(Animal):
    """A class used to represent a dog"""

    def __init__(self, name, age):
        super().__init__(name, age)
        self.type = "dog"


fufu = Dog(name="fufu", age=2)
print(fufu.speak())  # ouput: My name is fufu and I am 2 years old!

Notice the code above uses super() method, we always need to initialize the super class, especially when instance variables need to exist, also notice get get an error AttributeError: 'Dog' object has no attribute 'name' if we don't initialize the Animal class.

Overriding methods in inheritance

Inheritance also makes it possible to override existing methods, let us have a look with an example below:

code
class Animal:
    """A class used to represent an animal"""

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def speak(self):
        return f"My name is {self.name} and I am {self.age} years old!"


"""
Added a speak() method to Dog, this will now 
override the speak() method in Animal class
"""

class Dog(Animal):
    """A class used to represent a dog"""

    def __init__(self, name, age):
        super().__init__(name, age)

    # override the parent speak method
    def speak(self):
        return "called from dog class"


fufu = Dog(name="fufu", age=2)
print(fufu.speak())  # ouput: called from dog class

This gives us extra power to override any method from super classes whilst still inheriting other methods and instance variables.

issubclass function in Python

As we learn't previously, Python has inbuilt functions that we can call upon, issubclass is such a function. We can use it to check if an object is a subclass a class.

code
class Animal:
    """A class used to represent an animal"""

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def speak(self):
        return f"My name is {self.name} and I am {self.age} years old!"


class Dog(Animal):
    """A class used to represent a dog"""

    def __init__(self, name, age):
        super().__init__(name, age)

    # override the parent speak method
    def speak(self):
        return "called from dog class"

# check if Dog is subclass to Animal class
print(issubclass(Dog, Animal))  # ouput: True

That is how issubclass works, it returns a type of boolean

Multiple Inheritance in Python

In addition to single inheritance, Python supports multiple inheritance, in which a subclass can inherit from multiple superclasses, also known as sibling classes.

code
class Person:
    """Holds information about a person"""

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def print_name(self):
        print(self.name)

    def print_age(self):
        print(self.age)


class Student:
    """Returns a student's id"""

    def __init__(self, id):
        self.id = id

    def print_id(self):
        print(self.id)


"""
Resident uses multiple inheritance and therefore has
access to methods of both classes
"""


class Resident(Person, Student):
    """Gets information about a resident"""

    def __init__(self, name, age, id):
        Person.__init__(self, name, age)
        Student.__init__(self, id)


resident = Resident("Jennifer", 28, "109")

resident.print_name()  # output: Jennifer
resident.print_age()  # output: 28
resident.print_id()  # output: 109

Above shows it is possible to inherit from multiple classes in Python, now let's look at the method resolution order.

Method Resolution Order (MRO)

In Python, method resolution order (MRO) is the order in which a method or attribute is resolved.

First, the method or attribute looks up the current class then it follows the order we specified while inheriting.

Let's have a look at an example below:

code
'''
Person and Student both have title() method, Resident inherits from 
both of them, when we call title on the Resident object which of the
title() methods will get called?
'''

class Person:
    def title(self):
        print("In class Person")


class Student:
    def title(self):
        print("In class Student")


class Resident(Person, Student):
    pass


james = Resident()
james.title()  # output: In class Person


'''
We can also use Python's attribute __mro__ and method mro() to
print out the order of method execution.

output:
(<class '__main__.Resident'>, <class '__main__.Person'>, <class '__main__.Student'>, <class 'object'>)
[<class '__main__.Resident'>, <class '__main__.Person'>, <class '__main__.Student'>, <class 'object'>]
'''

print(Resident.__mro__)
print(Resident.mro())

To get the method resolution order of a class we can use either __mro__ attribute or mro() method. These will display the order in which methods are resolved, as shown above.

Final Thoughts

In this blog post, you learned how inheritance works in Python and the techniques to use super() method as well as handling single and multiple inheritances.

Finally, we touched on method resolution order (MRO) as well as how to use a method such as mro() to view the order of method resolution.

Keep on learning and practising object-oriented programming in Python.

Happy Coding...

If you found this post helpful, please share it with others.

MY STORY

My name is Kingsley Ijomah, I am the founder of CODEHANCE, an online education platform built with you in mind, a place where I express my gratitude to a skill ( coding ) which has changed my life completely.

Learn To Code With Me.
FREE course included.

GET IN TOUCH

Enter your email address:

Delivered by FeedBurner