Python Inheritance: Single, Overriding & Multiple Guide

1. Overview of Python Inheritance

In Python, inheritance is a mechanism where a child class inherits functionality and attributes from a parent class. This improves code reusability and streamlines maintenance. It is one of the key concepts of object-oriented programming (OOP), especially useful in large-scale system development and long-term projects.

Basic Roles of Inheritance

  • Code Reusability: Since the functionality of a class written once can be used by other classes, duplicate code can be avoided.
  • Ease of Maintenance: Changes to the parent class are automatically reflected in child classes, allowing efficient modifications and feature extensions.
class ParentClass:
    def greet(self):
        print("Hello, this is the parent class.")

class ChildClass(ParentClass):
    def greet(self):
        print("Hello, this is the child class.")
In this example, ChildClass overrides the methods of ParentClass. Because the greet method is overridden, the child class displays its own greeting.

2. Single Inheritance in Python

Single inheritance refers to a form where a single child class inherits functionality from a single parent class. This is the basic form of inheritance in Python, allowing you to keep code simple while still providing extensibility.

Basic Syntax and Example of Single Inheritance

class Car:
    def __init__(self, brand, color):
        self.brand = brand
        self.color = color

    def describe(self):
        print(f"This car is a {self.color} {self.brand}.")

class ElectricCar(Car):
    def __init__(self, brand, color, battery_size):
        super().__init__(brand, color)
        self.battery_size = battery_size

    def describe_battery(self):
        print(f"The battery capacity is {self.battery_size} kWh.")
In this example, the ElectricCar class inherits the functionality of the Car class while adding a description of battery capacity. It uses super() to call the parent class’s constructor and initialize common attributes (brand and color).

3. Method Overriding

Override is a feature that allows a subclass to redefine a method from its parent class. This enables you to leverage the parent class’s method while altering its behavior in the subclass.

Example of Overriding

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

class Dog(Animal):
    def speak(self):
        print("Woof!")
In this example, the Dog class overrides the Animal class’s speak method. As a result, an instance of the Dog class outputs “Woof”, while an instance of the Animal class displays “Animal sound”.

4. Multiple Inheritance

Multiple inheritance allows a single subclass to inherit from multiple parent classes. This lets you combine the functionality of different classes into one, but it can make the implementation more complex, so you need to be careful.

Example and Considerations for Multiple Inheritance

class A:
    def greet(self):
        print("Greeting from A")

class B:
    def greet(self):
        print("Greeting from B")

class C(A, B):
    pass

c = C()
c.greet()  # "Greeting from A" is displayed (the first class is prioritized according to the MRO)
In Python, the MRO (Method Resolution Order) determines which parent class’s method is called. To check this order, use C.mro(). Multiple inheritance is powerful, but you need to be aware of conflicts between parent classes and the method order.
侍エンジニア塾

5. Practical Example Using Inheritance

Inheritance is useful in everyday programming situations. For instance, in a company’s employee management system, inheriting from a basic employee class to create classes for specific positions enables code reuse and extension.

Example of a Practical Employee Management System

class Employee:
    def __init__(self, first, last, pay):
        self.first = first
        self.last = last
        self.pay = pay

    def fullname(self):
        return f'{self.first} {self.last}'

class Manager(Employee):
    def __init__(self, first, last, pay, employees=None):
        super().__init__(first, last, pay)
        self.employees = employees if employees is not None else []

    def add_employee(self, employee):
        if employee not in self.employees:
            self.employees.append(employee)

    def print_employees(self):
        for emp in self.employees:
            print(emp.fullname())
In this example, the Manager class inherits from the Employee class, adding employee management functionality. It maintains the parent class’s common features while extending capabilities specific to the role.

6. Best Practices for Inheritance vs. Composition

Inheritance is very powerful, but overusing it can make code more complex. In particular, multiple inheritance can complicate relationships between classes, so it should be used cautiously. In such cases, using composition instead of inheritance is recommended.

Example of Composition

Composition is a design pattern where a class holds another class as a component (instance), delegating functionality.
class Engine:
    def start(self):
        print("The engine has started.")

class Car:
    def __init__(self, engine):
        self.engine = engine

    def start(self):
        self.engine.start()

engine = Engine()
car = Car(engine)
car.start()  # "The engine has started." is printed
Thus, composition is a way to share functionality between classes without using inheritance. By giving classes only the functionality they need, the code becomes more flexible and easier to manage.

7. Summary

Inheritance in Python is a powerful tool for enhancing code reuse and extensibility. By understanding techniques such as single inheritance, multiple inheritance, and overriding, you can create efficient and maintainable programs. At the same time, it’s important to be mindful of when to use composition instead and design appropriately. Mastering proper inheritance will allow you to build a flexible and robust code base.
RUNTEQ(ランテック)|超実戦型エンジニア育成スクール