Python Inheritance with Examples

Inheritance is one of the fundamental concepts of object-oriented programming (OOP) that allows a class to inherit attributes and methods from another class. In Python, inheritance enables code reusability and the creation of hierarchical relationships between classes. This article will explain Python inheritance with practical examples to help you understand and implement this powerful feature.

Understanding Inheritance in Python

Inheritance creates a parent-child relationship between classes where:

  • The parent class (also called base class or superclass) is the class being inherited from
  • The child class (also called derived class or subclass) is the class that inherits from another class

The child class automatically gets access to all the methods and attributes of the parent class while being able to define its own unique features.

Basic Syntax

class ParentClass:
    # Parent class attributes and methods
    pass

class ChildClass(ParentClass):
    # Child class attributes and methods
    pass

Types of Inheritance in Python

Python supports several types of inheritance:

  1. Single Inheritance: A child class inherits from a single parent class
  2. Multiple Inheritance: A child class inherits from multiple parent classes
  3. Multilevel Inheritance: A child class inherits from a parent class which itself inherits from another class
  4. Hierarchical Inheritance: Multiple child classes inherit from a single parent class
  5. Hybrid Inheritance: A combination of two or more inheritance types

Practical Examples of Python Inheritance

Example 1: Single Inheritance

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

    def speak(self):
        return "Some sound"

# Child class inheriting from Animal
class Dog(Animal):
    def speak(self):
        return "Woof!"

# Create instances
animal = Animal("Generic Animal")
dog = Dog("Buddy")

print(animal.name, "says", animal.speak())  # Generic Animal says Some sound
print(dog.name, "says", dog.speak())       # Buddy says Woof!

In this example:

  • Dog inherits from Animal
  • Dog gets access to the __init__ method and name attribute from Animal
  • Dog overrides the speak method with its own implementation

Example 2: Multiple Inheritance

class Flyable:
    def fly(self):
        return "I can fly!"

class Swimmable:
    def swim(self):
        return "I can swim!"

class Duck(Flyable, Swimmable):
    def speak(self):
        return "Quack!"

duck = Duck()
print(duck.fly())    # I can fly!
print(duck.swim())   # I can swim!
print(duck.speak())  # Quack!

Here, the Duck class inherits from both Flyable and Swimmable, gaining methods from both parent classes.

Example 3: Multilevel Inheritance

class Vehicle:
    def __init__(self, make, model):
        self.make = make
        self.model = model

    def info(self):
        return f"{self.make} {self.model}"

class Car(Vehicle):
    def __init__(self, make, model, doors):
        super().__init__(make, model)
        self.doors = doors

    def info(self):
        return f"{super().info()} with {self.doors} doors"

class ElectricCar(Car):
    def __init__(self, make, model, doors, battery_size):
        super().__init__(make, model, doors)
        self.battery_size = battery_size

    def info(self):
        return f"{super().info()} and {self.battery_size}kWh battery"

tesla = ElectricCar("Tesla", "Model S", 4, 100)
print(tesla.info())  # Tesla Model S with 4 doors and 100kWh battery

This demonstrates a chain of inheritance: ElectricCarCarVehicle.

The super() Function

The super() function allows you to call methods from the parent class. This is particularly useful when:

  1. You want to extend the functionality of a parent method rather than completely override it
  2. You need to access parent class methods in multiple inheritance scenarios
class Parent:
    def __init__(self, name):
        self.name = name

class Child(Parent):
    def __init__(self, name, age):
        super().__init__(name)  # Calls Parent.__init__()
        self.age = age

child = Child("Alice", 10)
print(child.name)  # Alice
print(child.age)   # 10

Method Resolution Order (MRO)

In multiple inheritance, Python follows a specific order to search for methods and attributes. This is called Method Resolution Order (MRO). You can view the MRO of a class using the __mro__ attribute or the mro() method.

print(Duck.__mro__)
# Output: (<class '__main__.Duck'>, <class '__main__.Flyable'>, 
#          <class '__main__.Swimmable'>, <class 'object'>)

When to Use Inheritance

Inheritance is appropriate when:

  • There’s a clear “is-a” relationship between classes
  • You need to share common behavior among related classes
  • You want to extend or modify existing functionality

However, overusing inheritance can lead to complex, hard-to-maintain code. In some cases, composition (using objects as attributes) might be a better approach.

Conclusion

Python inheritance is a powerful mechanism for creating hierarchical class relationships and promoting code reuse. By understanding the different types of inheritance and how to properly use the super() function, you can design more efficient and organized object-oriented programs. Remember to use inheritance judiciously and consider composition as an alternative when appropriate.

The examples provided in this article demonstrate the core concepts of inheritance in Python, giving you a solid foundation to implement these techniques in your own projects.

Leave a Comment

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

Scroll to Top