Inheritance in Python

Loading

Inheritance is a fundamental concept in Object-Oriented Programming (OOP) that allows a child class to inherit attributes and methods from a parent class. This promotes code reuse, reduces redundancy, and improves maintainability.

Why Use Inheritance?

Code Reusability – Avoid duplicate code by reusing existing classes
Extensibility – Modify or extend behavior without changing the original class
Maintainability – Easier to manage and update code


1. Understanding Inheritance

1.1 Defining a Parent and Child Class

A child class inherits from a parent class by passing the parent class as a parameter.

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

def speak(self):
print("Animal makes a sound")

class Dog(Animal): # Child class
def __init__(self, name, breed):
super().__init__(name) # Call parent constructor
self.breed = breed

def speak(self): # Overriding parent method
print("Bark!")

dog = Dog("Buddy", "Golden Retriever")
dog.speak() # Output: Bark!

Here, Dog inherits from Animal, and the speak() method is overridden.


2. Types of Inheritance in Python

2.1 Single Inheritance

A child class inherits from a single parent class.

class Vehicle:
def __init__(self, brand):
self.brand = brand

def show(self):
print(f"Brand: {self.brand}")

class Car(Vehicle): # Inheriting from Vehicle
def __init__(self, brand, model):
super().__init__(brand)
self.model = model

def show(self):
print(f"Brand: {self.brand}, Model: {self.model}")

car = Car("Toyota", "Corolla")
car.show()

Output:

Brand: Toyota, Model: Corolla

2.2 Multiple Inheritance

A child class can inherit from multiple parent classes.

class Engine:
def start(self):
print("Engine started")

class Wheels:
def rotate(self):
print("Wheels rotating")

class Car(Engine, Wheels): # Multiple inheritance
def drive(self):
print("Car is moving")

car = Car()
car.start() # From Engine class
car.rotate() # From Wheels class

Output:

Engine started
Wheels rotating

Avoid multiple inheritance if it leads to complexity or ambiguity.


2.3 Multilevel Inheritance

A class inherits from another class, which itself inherits from another class.

class Grandparent:
def family_name(self):
print("Family: Smith")

class Parent(Grandparent):
def parent_name(self):
print("Parent: John")

class Child(Parent): # Child inherits from Parent
def child_name(self):
print("Child: Alice")

child = Child()
child.family_name() # Inherited from Grandparent
child.parent_name() # Inherited from Parent
child.child_name() # Defined in Child

Output:

Family: Smith
Parent: John
Child: Alice

2.4 Hierarchical Inheritance

Multiple child classes inherit from the same parent class.

class Animal:
def sound(self):
print("Some sound")

class Dog(Animal):
def sound(self):
print("Bark!")

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

dog = Dog()
cat = Cat()

dog.sound() # Output: Bark!
cat.sound() # Output: Meow!

2.5 Hybrid Inheritance

A combination of multiple inheritance and multilevel inheritance.

class A:
def method_A(self):
print("Method A")

class B(A):
def method_B(self):
print("Method B")

class C(A):
def method_C(self):
print("Method C")

class D(B, C): # Hybrid Inheritance
def method_D(self):
print("Method D")

obj = D()
obj.method_A() # From class A
obj.method_B() # From class B
obj.method_C() # From class C
obj.method_D() # From class D

Be cautious with Hybrid Inheritance as it can create a complex hierarchy.


3. Method Overriding in Inheritance

A child class can redefine a method from its parent class to change its behavior.

class Parent:
def show(self):
print("Parent class method")

class Child(Parent):
def show(self): # Overriding the parent method
print("Child class method")

child = Child()
child.show() # Output: Child class method

4. The super() Function

The super() function allows a child class to call a parent class method.

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

def display(self):
print(f"Name: {self.name}")

class Employee(Person):
def __init__(self, name, salary):
super().__init__(name) # Call parent constructor
self.salary = salary

def display(self):
super().display() # Call parent method
print(f"Salary: {self.salary}")

emp = Employee("Alice", 5000)
emp.display()

Output:

Name: Alice
Salary: 5000

5. The Method Resolution Order (MRO)

When multiple classes are inherited, Python follows the C3 linearization (Depth-First Left-to-Right Order) to resolve method calls.

class A:
def show(self):
print("Class A")

class B(A):
def show(self):
print("Class B")

class C(A):
def show(self):
print("Class C")

class D(B, C): # Multiple Inheritance
pass

obj = D()
obj.show() # Output: Class B (because B is first in the order)

Use ClassName.__mro__ or help(ClassName) to check the Method Resolution Order (MRO).

print(D.__mro__)

6. Real-World Example: Employee Management System

class Employee:
def __init__(self, name, salary):
self.name = name
self.salary = salary

def display(self):
print(f"Name: {self.name}, Salary: {self.salary}")

class Manager(Employee):
def __init__(self, name, salary, department):
super().__init__(name, salary)
self.department = department

def display(self):
super().display()
print(f"Department: {self.department}")

mgr = Manager("John", 8000, "HR")
mgr.display()

Output:

Name: John, Salary: 8000
Department: HR

Leave a Reply

Your email address will not be published. Required fields are marked *