Inheritance and Polymorphism in Python

Inheritance is a mechanism which allows us to create a new class – known as child class – that is based upon an existing class – the parent class, by adding new attributes and methods on top of the existing class. When you do so, the child class inherits attributes and methods of the parent class.

Inheritance really shines when you want to create classes that are very similar. All you need to do is to write the code for the things that they have common in one class – the parent class. And then write code for things that are very specific in a different class – the child class. This saves you from duplicating a lot of code.

Let’s take a more concrete example to illustrate this concept.

Suppose we are creating a program which deals with various shapes. Each shape has some common properties. For example, the color of the shape, whether it is filled or not and so on. In addition to that, there are some properties which vary from shape to shape. For example, area and perimeter. The area of the rectangle is width * length whereas the area of the circle is πr². At first, it might be tempting to create classes for different shapes like this:

Did you notice that amount of duplicate code we are writing?

Both classes share the same __color and __filled attribute as well as their getter and setter methods. To make the situation worse, If we want to update how any of these methods work, then we would have to visit each class one by one to make the necessary changes. By using inheritance, we can abstract out common properties to a general Shape class (parent class) and then we can create child classes such as Rectangle, Triangle and Circle that inherits from the Shape class. A child class inherits all the attributes and methods from its parent class, but it can also add attributes and methods of its own.

To create a child class based upon the parent class we use the following syntax:

In Object Oriented lingo, when a class c2 inherits from a class c1, we say class c2 extends class c1 or class c2 is derived from class c1.

The following program demonstrates inheritance in action. It creates a class named Shape, which contains attributes and methods common to all shapes, then it creates two child classes Rectangle and Triangle which contains attributes and methods specific to them only.

python101/Chapter-16/inheritance.py

Output:

In lines 3-19, we have defined a Shape class. It is a parent class and only contains attributes and methods common to all shapes. This class defines two private attributes __color and __filled, then it provides getter and setter methods for those attributes.

In lines 22-45, we have defined a Rectangle class which inherits from Shape class. Pay close attention to the syntax we are using.

inheritance

This line tells us that Rectangle class extends the Shape class or Rectangle class is a child class of Shape class. Thus the Rectangle class inherits attributes and methods defined in the Shape class. In addition to that, the Rectangle class adds two private attributes, getter and setter methods for private attributes, as well as methods to calculate the area and perimeter of the rectangle.

Notice the code in line 25.

In Python, we use super() function to call the parent class methods. So the above code calls Shape class’s __init__() method. This is required to set the values of attributes in the parent class. Otherwise, when you try to access values of attributes defined in the parent class using getter or setter methods, you will get an error.

Similarly, In lines 48-63 we have defined a Circle class. Just like Rectangle, it extends the Shape class and adds few attributes and methods of its own.

The code in lines 66-86, creates Rectangle and Circle object and then calls get_area(), get_perimeter(), get_filled(), get_color(), set_color() and set_filled() methods on these objects one by one. Notice how we are able to call methods which are defined in the same class, as well as methods which are defined on the parent class.

Multiple Inheritance

Python allows us to derive a class from several classes at once, this is known as Multiple Inheritance. Its general format is:

The ChildClass is derived from three classes ParentClass_1, ParentClass_2, ParentClass_3. As a result, it will inherit attributes and methods from all the three classes.

The following program demonstrates multiple inheritance in action:

python101/Chapter-16/multiple_inheritance.py

Output:

Polymorphism and Method Overriding

In literal sense, Polymorphism means the ability to take various forms. In Python, Polymorphism allows us to define methods in the child class with the same name as defined in their parent class.

As we know, a child class inherits all the methods from the parent class. However, you will encounter situations where the method inherited from the parent class doesn’t quite fit into the child class. In such cases, you will have to re-implement method in the child class. This process is known as Method Overriding.

If you have overridden a method in the child class, then the version of the method will be called based upon the type of the object used to call it. If a child class object is used to call an overridden method then the child class version of the method is called. On the other hand, if parent class object is used to call an overridden method, then the parent class version of the method is called.

The following program demonstrates method overriding in action:

python101/Chapter-16/method_overriding.py

Output:

Here b_obj is an object of class B (child class), as a result, class B version of the explore() method is called. However, the variable a_obj is an object of class A (parent class), as a result, class A version of the explore() method is called.

If for some reason you still want to access the overridden method of the parent class in the child class, you can call it using the super() function as follows:

python101/Chapter-16/method_overriding_2.py

Output:

object – The Base Class

In Python, all classes inherit from the object class implicitly. It means that the following two class definitions are equivalent.

It turns out that the object class provides some special methods with two leading and trailing underscores which are inherited by all the classes. Here are some important methods provided by the object class.

  1. __new__()
  2. __init__()
  3. __str__()

The __new__() method creates the object. After creating the object it calls the __init__() method to initialize attributes of the object. Finally, it returns the newly created object to the calling program. Normally, we don’t override __new__() method, however, if you want to significantly change the way an object is created, you should definitely override it.

The __str__() method is used to return a nicely formatted string representation of the object. The object class version of __str__() method returns a string containing the name of the class and its memory address in hexadecimal. For example:

python101/Chapter-16/__str__method.py

Output:

Sure, it is not very helpful. We can easily override this method by defining a method named __str__() in the Jester class as follows.

python101/Chapter-16/overriding__str__method.py

Output:

2 thoughts on “Inheritance and Polymorphism in Python

Leave a Comment

%d bloggers like this: