Inheritance and Polymorphism in Python

inheritance and polymorphism in python

Introduction to Inheritance and Polymorphism

As a beginner in Python programming language, you might have heard of inheritance and polymorphism. These are two essential concepts in object-oriented programming, which is Python’s primary programming paradigm. Understanding these concepts is crucial in building complex software systems.

What is Inheritance?

Inheritance is a mechanism that allows a new class to be based on an existing class. The new class, known as the derived class or subclass, inherits properties and behavior from the existing class, known as the base class or superclass. In simple terms, inheritance allows us to reuse code and avoid code duplication. It also facilitates code maintenance and makes the code more readable.

Consider the following example:

class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return "Woof!"

class Cat(Animal):
    def speak(self):
        return "Meow!"

dog = Dog("Buddy")
print(dog.speak()) # Output: Woof!

cat = Cat("Fluffy")
print(cat.speak()) # Output: Meow!

In this example, we have two classes: Animal and its derived classes, Dog and Cat. Both Dog and Cat classes inherit from Animal class and have their own implementation of the speak method. When we create a Dog object, it calls the speak method of the Dog class, and when we create a Cat object, it calls the speak method of the Cat class.

Understanding Polymorphism in Python

Polymorphism is a concept that allows an object to take on different forms or shapes. In Python, polymorphism is achieved through method overriding and method overloading. Method overriding is when a subclass provides its own implementation of a method that is already defined in its superclass. Method overloading is when a class has multiple methods with the same name, but different parameters.

Consider the following example:

class Shape:
    def area(self):
        pass

class Rectangle(Shape):
    def __init__(self, length, breadth):
        self.length = length
        self.breadth = breadth

    def area(self):
        return self.length * self.breadth

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return 


What is Inheritance?

Inheritance is a fundamental concept in object-oriented programming, where a new class is created by inheriting properties and behavior from an existing class. The existing class is called the base class or superclass, while the new class is called the derived class or subclass. The derived class can add new functionality, modify existing behavior or use the inherited functionality of the base class.

The main advantage of inheritance is code reusability, which means that you can write a class once and use it in multiple places without duplicating the same code. It also helps in code maintenance as any changes made in the base class automatically reflect in the derived classes.

In Python, inheritance is achieved by creating a new class and specifying the base class in parentheses after the class name. It allows the derived class to access the properties and methods of the base class.

Let’s take an example to understand inheritance in Python better. Consider we have a base class called Person, which has two attributes, name and age, and a method called introduce. We can create a derived class called Student, which extends the Person class and has an additional attribute called id and a method called study.

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

    def introduce(self):
        print(f"Hi, my name is {self.name}, and I am {self.age} years old.")

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

    def study(self):
        print(f"{self.name} is studying.")

student1 = Student("John", 20, 123)
student1.introduce() # Output: Hi, my name is John, and I am 20 years old.
student1.study() # Output: John is studying.

In this example, the Student class inherits the attributes and method of the Person class and adds an additional attribute and method. We create an object of the Student class and call the introduce and study methods, which outputs the respective messages.

In conclusion, inheritance is a powerful feature of object-oriented programming that allows creating new classes based on existing classes. It promotes code reusability, maintenance, and readability.

Understanding Polymorphism in Python

Polymorphism is another crucial concept in object-oriented programming, which allows objects of different classes to be used interchangeably. In Python, polymorphism is achieved through method overriding and method overloading.

Method overriding is when a subclass provides its own implementation of a method that is already defined in its superclass. The method in the subclass has the same name, same parameter list, and same return type as the method in the superclass. When the method is called on an object of the subclass, it overrides the implementation of the method in the superclass.

Let’s understand method overriding with an example. Consider we have a base class called Animal with a method called speak. We create a derived class called Dog, which overrides the speak method and provides its own implementation.

class Animal:
    def speak(self):
        print("Animal speaks.")

class Dog(Animal):
    def speak(self):
        print("Dog barks.")

animal = Animal()
animal.speak() # Output: Animal speaks.

dog = Dog()
dog.speak() # Output: Dog barks.

In this example, the speak method of the Dog class overrides the speak method of the Animal class. When we call the speak method on the animal object, it uses the implementation of the method in the Animal class. When we call the speak method on the dog object, it uses the implementation of the method in the Dog class.

Method overloading is when a class has multiple methods with the same name, but different parameters. Python does not support method overloading directly, but we can achieve it through default arguments or variable-length arguments.

Let’s understand method overloading with an example. Consider we have a class called Calculator that can perform addition with two or three numbers. We define two methods with the same name add, but different parameters.

class Calculator:
    def add(self, num1, num2):
        print(num1 + num2)

    def add(self, num1, num2, num3):
        print(num1 + num2 + num3)

calculator = Calculator()
calculator.add(2, 3) # Output: TypeError: add() missing 1 required positional argument: 'num3'

calculator.add(2, 3, 4) # Output: 9

In this example, we define two methods named add in the Calculator class, one that takes two parameters and another that takes

Types of Polymorphism in Python

In addition to method overriding and method overloading, there are two other types of polymorphism in Python: duck typing and operator overloading.

Duck typing is a concept where the type or the class of an object is less important than the methods and attributes it defines. It is called “duck typing” because it is based on the saying, “If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck.” In Python, we can use duck typing to create flexible and generic code that can work with different types of objects.

Let’s understand duck typing with an example. Consider we have two classes, Circle and Square, which have a method called area. We create a function called calculate_area, which takes an object and calculates its area. We can pass an object of either Circle or Square class to this function as long as it has an area method.

class Circle:
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return 3.14 * self.radius ** 2

class Square:
    def __init__(self, side):
        self.side = side

    def area(self):
        return self.side ** 2

def calculate_area(shape):
    return shape.area()

circle = Circle(5)
square = Square(4)

print(calculate_area(circle)) # Output: 78.5
print(calculate_area(square)) # Output: 16

In this example, we define two classes, Circle and Square, which have an area method. We create a function called calculate_area, which takes an object and calculates its area. We can pass an object of either Circle or Square class to this function as long as it has an area method. When we call the calculate_area function with a Circle object, it calls the area method of the Circle class, and when we call it with a Square object, it calls the area method of the Square class.

Operator overloading is a concept where the operators such as +, -, *, /, etc. can be overloaded to work with user-defined objects. In Python, we can overload operators by defining special methods such as __add__, __sub__, __mul__, __div__, etc.

Let’s understand operator overloading with an example. Consider we have a class called Point, which represents a point in

Final Thought: Importance of Inheritance and Polymorphism in Python

Inheritance and polymorphism are crucial concepts in object-oriented programming, which allows us to write more flexible, reusable, and maintainable code.

Inheritance helps in reducing code duplication and promotes code reuse by allowing the derived class to inherit the properties and methods of the base class. It also facilitates code maintenance and makes the code more readable by keeping the related code in a single place.

Polymorphism allows objects of different classes to be used interchangeably, making the code more flexible and adaptable. Method overriding and method overloading are two ways of implementing polymorphism in Python. Method overriding allows the subclass to provide its own implementation of a method that is already defined in its superclass, whereas method overloading allows a class to have multiple methods with the same name but different parameters.

Python also supports duck typing and operator overloading as two other types of polymorphism. Duck typing allows us to write generic code that can work with different types of objects as long as they have the required attributes and methods. Operator overloading allows us to define how the operators should work with user-defined objects.

In conclusion, inheritance and polymorphism are essential concepts in Python programming that can help us write more flexible, reusable, and maintainable code. By understanding these concepts, we can create more complex software systems that are easier to maintain and extend.

You May Also Like