Tutorial

Inheritance in Python

7 min read

Inheritance is a fundamental concept in object-oriented programming (OOP) that allows classes to inherit attributes and methods from other classes. It provides a mechanism for creating new classes based on existing ones, thereby promoting code reuse and enhancing the organization and modularity of a program. Python, being an object-oriented programming language, fully supports inheritance and provides powerful tools to implement it effectively.

Inheritance establishes a parent-child relationship between classes, where the child class (also known as the derived class or subclass) inherits the properties of the parent class (also known as the base class or superclass).

This means that the child class can access and utilize the attributes and methods defined in the parent class without having to redefine them. In addition, the child class can extend or modify the inherited behavior by adding new attributes or methods or overriding the existing ones.

Syntax for Inheritance in Python

To implement inheritance in Python, we use the syntax:

class ChildClass(ParentClass):
    # Class body

Here, ChildClass is the name of the child’s class, and ParentClass is the name of the parent class. The child class can inherit from multiple parent classes, forming a hierarchy of classes.

In Python, inheritance allows us to build complex class hierarchies and create specialized classes that inherit and extend the behavior of more general classes. It promotes code reusability, enhances the readability of the code, and simplifies maintenance and updates.

Single Inheritance in Python

Single inheritance in Python refers to the process of creating a new class that inherits the attributes and methods of a single-parent class. It establishes a hierarchical relationship where the child class inherits all the characteristics of the parent class while being able to add its own unique attributes and methods.

Example of single inheritance in Python-

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

    def eat(self):
        print(f"{self.name} is eating.")

class Dog(Animal):
    def bark(self):
        print("Woof!")

dog = Dog("Buddy")
dog.eat()  # Inherited from Animal class
dog.bark()  # Defined in Dog class

Output:

Buddy is eating.
Woof!

Here, the Animal class is the parent class, and the Dog class is the child class inheriting from Animal. The Dog class inherits the eat() method from the Animal class and defines its own method bark(). The dog object can access both the inherited method eat() and the unique method bark().

Multiple Inheritance in Python

Multiple inheritance in Python refers to the ability of a class to inherit attributes and methods from multiple parent classes. It allows a child class to combine functionalities from multiple sources, incorporating the characteristics of multiple parent classes into a single derived class.

Example of multiple inheritance in Python-

class A:
    def method(self):
        print("Method from class A")

class B:
    def method(self):
        print("Method from class B")

class C(A, B):
    pass

c = C()
c.method()  # Method resolution order follows C -> A -> B

Output:

Method from class A

Here, we have three classes: A, B, and C. Class C inherits from both A and B using multiple inheritance. When the method() is called on the c object, Python looks for the method in C first, then in A, and finally in B. Since C inherits from A, the method from A is executed.

Method Overriding in Python Inheritance

Method overriding is a fundamental aspect of inheritance in Python.

It allows a child class to provide its own implementation of a method that is already defined in its parent class. By overriding a method, the child class can customize the behavior of the inherited method to suit its specific needs.

To override a method in Python, the child class simply redefines the method with the same name as the method in the parent class. When an object of the child class calls the overridden method, the implementation in the child class is executed instead of the parent class.

Example of method overriding in Python Inheritance-

class Animal:
    def make_sound(self):
        print("Generic animal sound.")

class Dog(Animal):
    def make_sound(self):
        print("Woof!")

class Cat(Animal):
    def make_sound(self):
        print("Meow!")

# Creating objects of the child classes
dog = Dog()
cat = Cat()

# Calling the overridden method
dog.make_sound()  # Output: Woof!
cat.make_sound()  # Output: Meow!

Here, we have a parent class Animal with a method make_sound(). The child classes Dog and Cat override the make_sound() method with their own implementations.

When the make_sound() method is called on a dog object, the overridden method in the Dog class is executed, resulting in the output “Woof!”.

Similarly, when the method is called on a cat object, the overridden method in the Cat class is executed, producing the output “Meow!”.

The super() Method in Python Inheritance

In Python inheritance, the super() method plays a crucial role in facilitating the interaction between a child class and its parent class.

It provides a way to access and invoke methods or constructors defined in the parent class, enabling the child class to extend or augment the behavior of the parent class.

The super() method is typically used within the child class to call the parent class’s methods or constructors. By doing so, it allows the child class to utilize the existing functionality implemented in the parent class while adding its own modifications.

Example:

class Parent:
    def __init__(self):
        self.parent_var = "I am from the parent class."

    def print_info(self):
        print("This is the parent class.")

class Child(Parent):
    def __init__(self):
        super().__init__()  # Calling the parent class's constructor
        self.child_var = "I am from the child class."

    def print_info(self):
        super().print_info()  # Calling the parent class's method
        print("This is the child class.")

# Creating an object of the child class
child = Child()

# Accessing the variables and invoking methods
print(child.parent_var)  # Output: I am from the parent class.
print(child.child_var)  # Output: I am from the child class.
child.print_info()  # Output: This is the parent class. This is the child class.

Here, the Child class inherits from the Parent class.

The Child class’s constructor uses super() to call the parent class’s constructor, ensuring that the initialization steps in the parent class are executed. This allows the child class to inherit and utilize the parent_var attribute.

Similarly, the Child class overrides the print_info() method, but within the overridden method, it calls super().print_info() to invoke the parent class’s print_info() method.

This way, the child class can add its own behavior while maintaining the functionality provided by the parent class.

The super() method is a powerful tool when working with inheritance, as it ensures proper coordination and cooperation between the parent and child classes. It allows for code reuse, modularity, and flexibility in implementing complex class hierarchies.

Applications of Inheritance in Python

Here are some common applications of inheritance:

  • Code Reusability: Inheritance allows us to reuse code from existing classes. By inheriting from a base class, we can acquire its attributes and methods, reducing code duplication. This promotes modular and maintainable code, as changes made in the base class automatically propagate to the derived classes.
  • Specialization and Generalization: Inheritance facilitates the creation of specialized classes that inherit from more general classes. This enables us to model real-world relationships and hierarchies. For example, a “Vehicle” base class can have derived classes like “Car,” “Motorcycle,” and “Truck,” each with its own specific attributes and behaviors.
  • Method Overriding: Inheritance allows child classes to override methods inherited from parent classes. This is useful when we want to modify the behavior of a method in a child class without changing the parent class implementation. It promotes customization and fine-tuning of functionalities.
  • Polymorphism: Inheritance, along with method overriding, enables polymorphism. Polymorphism allows objects of different classes to be treated as objects of a common base class. This provides flexibility and allows for more generic code that can work with different types of objects.
  • Interface Definition: Inheritance can be used to define interfaces or abstract classes that establish a common set of methods that derived classes must implement. This helps in enforcing a certain structure and ensures that derived classes adhere to a specific contract.
  • Multiple Inheritance: Python supports multiple inheritance, where a class can inherit from multiple parent classes. This feature allows us to combine functionalities from different classes, promoting code reuse and flexibility. However, it requires careful management to avoid conflicts or ambiguity.
  • Frameworks and Libraries: Inheritance is extensively used in frameworks and libraries to provide a foundation for developers to build upon. Frameworks often define base classes with default behaviors, and developers extend those classes to customize and add their specific functionalities.