Polymorphism and Inheritance in Python
Polymorphism and Inheritance in Python
This lesson will cover what polymorphism is and how to implement them in Python. Also,
you’ll learn how to implement polymorphism using function overloading, method
overriding, and operator overloading.
For example, Jessa acts as an employee when she is at the office. However, when she is at
home, she acts like a wife. Also, she represents herself differently in different places.
Therefore, the same person takes different forms as per the situation.
The built-in function len() calculates the length of an object depending upon its type. If an
object is a string, it returns the count of characters, and If an object is a list, it returns the
count of items in a list.
Example:
# calculate count
print(len(students))
print(len(school))
Output
10
Polymorphic
len() function
In this example, we have a vehicle class as a parent and a ‘Car’ and ‘Truck’ as its sub-class.
But each vehicle can have a different seating capacity, speed, etc., so we can have the
same instance method name in each class but with a different implementation. Using this
code can be extended and easily maintained over time.
Polymorphis
m with Inheritance
class Vehicle:
def show(self):
print('Details:', self.name, self.color, self.price)
def max_speed(self):
print('Vehicle max speed is 150')
def change_gear(self):
print('Vehicle change 6 gear')
def change_gear(self):
print('Car change 7 gear')
# Car Object
car = Car('Car x1', 'Red', 20000)
car.show()
# calls methods from Car class
car.max_speed()
car.change_gear()
# Vehicle Object
vehicle = Vehicle('Truck x1', 'white', 75000)
vehicle.show()
# calls method from a Vehicle class
vehicle.max_speed()
vehicle.change_gear()
Output:
As you can see, due to polymorphism, the Python interpreter recognizes that
the max_speed() and change_gear() methods are overridden for the car object. So, it uses the
one defined in the child class (Car)
On the other hand, the show() method isn’t overridden in the Car class, so it is used from
the Vehicle class.
In Python, we can change the default behavior of the built-in functions. For example, we
can change or extend the built-in functions such as len(), abs(), or divmod() by redefining
them in our class. Let’s see the example.
Example
def __len__(self):
print('Redefine length')
count = len(self.basket)
# count total items in a different way
# pair of shoes and shir+pant
return count * 2
Output
Redefine length
Python allows different classes to have methods with the same name.
Let’s design a different class in the same way by adding the same methods in two or
more classes.
Next, create an object of each class
Next, add all objects in a tuple.
In the end, iterate the tuple using a for loop and call methods of a object without
checking its class.
Example
class Ferrari:
def fuel_type(self):
print("Petrol")
def max_speed(self):
print("Max speed 350")
class BMW:
def fuel_type(self):
print("Diesel")
def max_speed(self):
print("Max speed is 240")
ferrari = Ferrari()
bmw = BMW()
Output
Petrol
Diesel
As you can see, we have created two classes Ferrari and BMW. They have the same instance
method names fuel_type() and max_speed(). However, we have not linked both the classes
nor have we used inheritance.
We packed two different objects into a tuple and iterate through it using a car variable. It is
possible due to polymorphism because we have added the same method in both classes
Python first checks the object’s class type and executes the method present in its class.
We can create polymorphism with a function that can take any object as a parameter and
execute its method without checking its class type. Using this, we can call object actions
using the same function instead of repeating method calls.
Example
class Ferrari:
def fuel_type(self):
print("Petrol")
def max_speed(self):
print("Max speed 350")
class BMW:
def fuel_type(self):
print("Diesel")
def max_speed(self):
print("Max speed is 240")
# normal function
def car_details(obj):
obj.fuel_type()
obj.max_speed()
ferrari = Ferrari()
bmw = BMW()
car_details(ferrari)
car_details(bmw)
Output
Petrol
Diesel
The built-in function reversed(obj) returns the iterable by reversing the given object. For
example, if you pass a string to it, it will reverse it. But if you pass a list of strings to it, it will
return the iterable by reversing the order of elements (it will not reverse the individual
string).
Let us see how a built-in method process objects having different data types.
Example:
print('Reverse string')
for i in reversed('PYnative'):
print(i, end=' ')
print('\nReverse list')
for i in reversed(['Emma', 'Jessa', 'Kelly']):
print(i, end=' ')
Output:
Reverse string
e v i t a n Y P
Reverse list
Method Overloading
The process of calling the same method with different parameters is known as method
overloading. Python does not support method overloading. Python considers only the
latest defined method even if you overload the method. Python will raise a TypeError if you
overload the method.
Example
Run
To overcome the above problem, we can use different ways to achieve the method
overloading. In Python, to overload the class method, we need to write the method’s logic
so that different code executes inside the function depending on the parameter passes.
For example, the built-in function range() takes three parameters and produce different
result depending upon the number of parameters passed to it.
Example:
Run
Output:
0, 1, 2, 3, 4,
5, 6, 7, 8, 9,
2, 4, 6, 8, 10,
Let’s assume we have an area() method to calculate the area of a square and rectangle. The
method will calculate the area depending upon the number of parameters passed to it.
class Shape:
# function with two default parameters
def area(self, a, b=0):
if b > 0:
print('Area of Rectangle is:', a * b)
else:
print('Area of Square is:', a ** 2)
square = Shape()
square.area(5)
rectangle = Shape()
rectangle.area(5, 3)
Output:
For example, the + operator will perform an arithmetic addition operation when used with
numbers. Likewise, it will perform concatenation when used with strings.
The operator + is used to carry out different operations for distinct data types. This is one
of the most simple occurrences of polymorphism in Python.
Example:
# add 2 numbers
print(100 + 200)
Output:
300
JessRoy
Suppose we have two objects, and we want to add these two objects with a
binary + operator. However, it will throw an error if we perform addition because the
compiler doesn’t add two objects. See the following example for more details.
Example:
class Book:
def __init__(self, pages):
self.pages = pages
Output
We can overload + operator to work with custom objects also. Python provides some
special or magic function that is automatically invoked when associated with that particular
operator.
Example:
class Book:
def __init__(self, pages):
self.pages = pages
b1 = Book(400)
b2 = Book(300)
print("Total number of pages: ", b1 + b2)
Output
Overloading the * Operator
Example:
class Employee:
def __init__(self, name, salary):
self.name = name
self.salary = salary
class TimeSheet:
def __init__(self, name, days):
self.name = name
self.days = days
Output
Magic Methods: In Python, there are different magic methods available to perform
overloading operations. The below table shows the magic methods names to overload the
mathematical operator, assignment operator, and relational operators in Python.
magic methods
Inheritance in Python
The process of inheriting the properties of the parent class into a child class is called inheritance. The
existing class is called a base class or parent class and the new class is called a subclass or child class or
derived class.
In this Python lesson, you will learn inheritance, method overloading, method overriding, types of
inheritance, and MRO (Method Resolution Order). In Object-oriented programming, inheritance is an
important aspect. The main purpose of inheritance is the reusability of code because we can use the
existing class to create a new class instead of creating it from scratch.
In inheritance, the child class acquires all the data members, properties, and functions from the parent class.
Also, a child class can also provide its specific implementation to the methods of the parent class.
For example, In the real world, Car is a sub-class of a Vehicle class. We can create a Car by inheriting the
properties of a Vehicle such as Wheels, Colors, Fuel tank, engine, and add extra properties in Car as
required.
Syntax
class BaseClass:
Body of base class
class DerivedClass(BaseClass):
Body of derived class
Types Of Inheritance: In Python, based upon the number of child and parent
classes involved, there are five types of inheritance. The type of inheritance are listed below:
1. Single inheritance
2. Multiple Inheritance
3. Multilevel inheritance
4. Hierarchical Inheritance
5. Hybrid Inheritance
Single Inheritance
In single inheritance, a child class inherits from a single-parent class. Here is one child class and one parent
class.
Let’s create one parent class called ClassOne and one child class called ClassTwo to implement single
inheritance.
# Base class
class Vehicle:
def Vehicle_info(self):
print('Inside Vehicle class')
# Child class
class Car(Vehicle):
def car_info(self):
print('Inside Car class')
Output
# Parent class 1
class Person:
def person_info(self, name, age):
print('Inside Person class')
print('Name:', name, 'Age:', age)
# Parent class 2
class Company:
def company_info(self, company_name, location):
print('Inside Company class')
print('Name:', company_name, 'location:', location)
# Child class
class Employee(Person, Company):
def Employee_info(self, salary, skill):
print('Inside Employee class')
print('Salary:', salary, 'Skill:', skill)
# access data
emp.person_info('Jessa', 28)
emp.company_info('Google', 'Atlanta')
emp.Employee_info(12000, 'Machine Learning')
Output
Multilevel inheritance
In multilevel inheritance, a class inherits from a child class or derived class. Suppose three classes A, B, C.
A is the superclass, B is the child class of A, C is the child class of B. In other words, we can say a chain of
classes is called multilevel inheritance.
Example
# Base class
class Vehicle:
def Vehicle_info(self):
print('Inside Vehicle class')
# Child class
class Car(Vehicle):
def car_info(self):
print('Inside Car class')
# Child class
class SportsCar(Car):
def sports_car_info(self):
print('Inside SportsCar class')
Output
In the above example, we can see there are three classes named Vehicle, Car, SportsCar. Vehicle is the
superclass, Car is a child of Vehicle, SportsCar is a child of Car. So we can see the chaining of classes.
Hierarchical Inheritance
In Hierarchical inheritance, more than one child class is derived from a single parent class. In other words,
we can say one parent class and multiple child classes.
Python hierarchical inheritance
Example
Let’s create ‘Vehicle’ as a parent class and two child class ‘Car’ and ‘Truck’ as a parent class.
class Vehicle:
def info(self):
print("This is Vehicle")
class Car(Vehicle):
def car_info(self, name):
print("Car name is:", name)
class Truck(Vehicle):
def truck_info(self, name):
print("Truck name is:", name)
obj1 = Car()
obj1.info()
obj1.car_info('BMW')
obj2 = Truck()
obj2.info()
obj2.truck_info('Ford')
Output
This is Vehicle
This is Vehicle
Hybrid Inheritance
When inheritance is consists of multiple types or a combination of different inheritance is called hybrid
inheritance.
Example
class Vehicle:
def vehicle_info(self):
print("Inside Vehicle class")
class Car(Vehicle):
def car_info(self):
print("Inside Car class")
class Truck(Vehicle):
def truck_info(self):
print("Inside Truck class")
# create object
s_car = SportsCar()
s_car.vehicle_info()
s_car.car_info()
s_car.sports_car_info()
Another is SportsCar inherit from two parent classes named Car and Vehicle. This is multiple inheritance.
Python super() function
When a class inherits all properties and behavior from the parent class is called inheritance. In such a case,
the inherited class is a subclass and the latter class is the parent class.
In child class, we can refer to parent class by using the super() function. The super function returns a
temporary object of the parent class that allows us to call a parent class method inside a child class method.
1. We are not required to remember or specify the parent class name to access its methods.
2. We can use the super() function in both single and multiple inheritances.
3. The super() function support code reusability as there is no need to write the entire function
Example
class Company:
def company_name(self):
return 'Google'
class Employee(Company):
def info(self):
# Calling the superclass method using super()function
c_name = super().company_name()
print("Jessa works at", c_name)
# Creating object of child class
emp = Employee()
emp.info()
Output:
In the above example, we create a parent class Company and child class Employee. In Employee class, we call
the parent class method by using a super() function.
issubclass()
In Python, we can verify whether a particular class is a subclass of another class. For this purpose, we can
use Python built-in function issubclass(). This function returns True if the given class is the subclass of the
specified class. Otherwise, it returns False.
Syntax
issubclass(class, classinfo)
Where,
class Company:
def fun1(self):
print("Inside parent class")
class Employee(Company):
def fun2(self):
print("Inside child class.")
class Player:
def fun3(self):
print("Inside Player class.")
# Result True
print(issubclass(Employee, Company))
# Result False
print(issubclass(Employee, list))
# Result False
print(issubclass(Player, Company))
# Result True
print(issubclass(Employee, (list, Company)))
# Result True
print(issubclass(Company, (list, Company)))
Method Overriding
In inheritance, all members available in the parent class are by default available in the child class. If the
child class does not satisfy with parent class implementation, then the child class is allowed to redefine that
method by extending additional functions in the child class. This concept is called method overriding.
When a child class method has the same name, same parameters, and same return type as a method in its
superclass, then the method in the child is said to override the method in the parent class.
Example
class Vehicle:
def max_speed(self):
print("max speed is 100 Km/Hour")
class Car(Vehicle):
# overridden the implementation of Vehicle class
def max_speed(self):
print("max speed is 200 Km/Hour")
Output:
In the above example, we create two classes named Vehicle (Parent class) and Car (Child class). The class
Car extends from the class Vehicle so, all properties of the parent class are available in the child class. In
addition to that, the child class redefined the method max_speed().
This order is also called the Linearization of a class, and a set of rules is called MRO (Method Resolution
Order). The MRO plays an essential role in multiple inheritances as a single method may found in
multiple parent classes.
Example
class A:
def process(self):
class B(A):
def process(self):
def process(self):
C1 = C()
C1.process()
print(C.mro())
# In class C
In the above example, we create three classes named A, B and C. Class B is inherited from A, class C inherits
from B and A. When we create an object of the C class and calling the process() method, Python looks for
the process() method in the current class in the C class itself.
Then search for parent classes, namely B and A, because C class inherit from B and A. that is, C(B, A) and
always search in left to right manner.
A class that consists of one or more abstract method is called the abstract class. Abstract methods
do not contain their implementation. Abstract class can be inherited by the subclass and abstract
method gets its definition in the subclass. Abstraction classes are meant to be the blueprint of the
other class. An abstract class can be useful when we are designing large functions. An abstract
class is also helpful to provide the standard interface for different implementations of components.
Python provides the abc module to use the abstraction in the Python program. Let's see the
following syntax.
Syntax
1. from abc import ABC
2. class ClassName(ABC):
Example -
1. # Python program demonstrate
2. # abstract base class work
3. from abc import ABC, abstractmethod
4. class Car(ABC):
5. def mileage(self):
6. pass
7.
8. class Tesla(Car):
9. def mileage(self):
10. print("The mileage is 30kmph")
11. class Suzuki(Car):
12. def mileage(self):
13. print("The mileage is 25kmph ")
14. class Duster(Car):
15. def mileage(self):
16. print("The mileage is 24kmph ")
17.
18. class Renault(Car):
19. def mileage(self):
20. print("The mileage is 27kmph ")
21.
22. # Driver code
23. t= Tesla ()
24. t.mileage()
25.
26. r = Renault()
27. r.mileage()
28.
29. s = Suzuki()
30. s.mileage()
31. d = Duster()
32. d.mileage()
Output:
Explanation -
In the above code, we have imported the abc module to create the abstract base class. We
created the Car class that inherited the ABC class and defined an abstract method named
mileage(). We have then inherited the base class from the three different subclasses and
implemented the abstract method differently. We created the objects to call the abstract method.
Points to Remember
Below are the points which we should remember about the abstract base class in Python.
o An Abstract class can contain the both method normal and abstract method.
o An Abstract cannot be instantiated; we cannot create objects for the abstract class.
Abstraction is essential to hide the core functionality from the users. We have covered the all the
basic concepts of Abstraction in Python.