Home » Python Inheritance Tutorial

Python Inheritance Tutorial

Inheritance is a fundamental concept in object-oriented programming (OOP) that allows a class (called a subclass) to inherit attributes and methods from another class (called a superclass or parent class).

This feature enables code reuse and the creation of more specialized classes that build on the functionality of existing ones.

In Python, inheritance provides a way to establish relationships between classes, where subclasses can override or extend the behavior of their parent classes.

This tutorial will explore various aspects of inheritance in Python with practical examples, including single inheritance, multiple inheritance, method overriding, and more.

1. Basic Inheritance

In Python, inheritance is implemented by passing the parent class as an argument to the child class during its definition. The child class will inherit all methods and attributes from the parent class.

Example: Basic Inheritance

# Example: Basic inheritance
class Animal:
    def __init__(self, name):
        self.name = name

    def make_sound(self):
        return "Some generic sound"

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

# Creating an object of the Dog class
dog = Dog("Buddy")

# Accessing inherited and unique methods
print(dog.name)          # Output: Buddy (inherited from Animal)
print(dog.make_sound())  # Output: Some generic sound (inherited from Animal)
print(dog.bark())        # Output: Woof! (method specific to Dog)

In this example:

The Dog class inherits the attributes and methods from the Animal class, such as name and make_sound().
The Dog class has its unique method bark(), which is not present in the Animal class.

2. Overriding Methods

Subclasses can override methods of their parent class. This means that the subclass provides its own implementation of the method, replacing the parent class’s version.

Example: Method Overriding

# Example: Overriding a method in the subclass
class Animal:
    def make_sound(self):
        return "Some generic sound"

class Dog(Animal):
    def make_sound(self):
        return "Bark!"

# Creating an object of the Dog class
dog = Dog()

# Calling the overridden method
print(dog.make_sound())  # Output: Bark!

In this example:

The Dog class overrides the make_sound() method of the Animal class to provide its own implementation (Bark!), replacing the generic sound defined in Animal.

3. Using super() to Call Parent Class Methods

When overriding methods, you might still want to call the parent class’s method in addition to your own implementation. The super() function allows you to access methods from the parent class.

Example: Using super() in Method Overriding

# Example: Using super() to call a method from the parent class
class Animal:
    def __init__(self, name):
        self.name = name

    def make_sound(self):
        return "Some generic sound"

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

    def make_sound(self):
        # Call the parent class's make_sound method and extend its functionality
        parent_sound = super().make_sound()
        return f"{parent_sound} and Bark!"

# Creating an object of the Dog class
dog = Dog("Buddy", "Golden Retriever")

# Accessing attributes and methods
print(dog.name)          # Output: Buddy
print(dog.breed)         # Output: Golden Retriever
print(dog.make_sound())  # Output: Some generic sound and Bark!

In this example:

super() is used to call the parent class’s __init__() method to initialize the name attribute.
The make_sound() method in Dog calls the parent class’s make_sound() using super() and extends it with additional functionality.

4. Multiple Inheritance

Python supports multiple inheritance, where a subclass can inherit from more than one parent class. This feature allows a subclass to combine functionalities from multiple parent classes.

Example: Multiple Inheritance

# Example: Multiple inheritance
class Animal:
    def make_sound(self):
        return "Some generic sound"

class Canine:
    def run(self):
        return "Running like a canine"

class Dog(Animal, Canine):
    def bark(self):
        return "Bark!"

# Creating an object of the Dog class
dog = Dog()

# Accessing methods from both parent classes
print(dog.make_sound())  # Output: Some generic sound (from Animal)
print(dog.run())         # Output: Running like a canine (from Canine)
print(dog.bark())        # Output: Bark! (method specific to Dog)

In this example:

The Dog class inherits from both Animal and Canine, gaining access to methods from both parent classes (make_sound() from Animal and run() from Canine).

5. The isinstance() and issubclass() Functions

Python provides the isinstance() and issubclass() functions to check relationships between instances and classes in the context of inheritance.

isinstance(object, class): Returns True if the object is an instance of the class (or any of its subclasses).
issubclass(subclass, class): Returns True if the subclass is a derived class of the specified class.

Example: Using isinstance() and issubclass()

# Example: Using isinstance() and issubclass()
class Animal:
    pass

class Dog(Animal):
    pass

dog = Dog()

# Checking if dog is an instance of Dog and Animal
print(isinstance(dog, Dog))    # Output: True
print(isinstance(dog, Animal)) # Output: True

# Checking subclass relationships
print(issubclass(Dog, Animal))  # Output: True
print(issubclass(Animal, Dog))  # Output: False

In this example:

isinstance() checks whether the dog object is an instance of both Dog and Animal.
issubclass() checks if Dog is a subclass of Animal.

6. Method Resolution Order (MRO)

In Python, Method Resolution Order (MRO) determines the order in which base classes are checked when calling a method. Python uses the C3 Linearization Algorithm to determine the MRO. The __mro__ attribute or the mro() method can be used to check the MRO of a class.

Example: Method Resolution Order (MRO) in Multiple Inheritance

# Example: MRO in multiple inheritance
class Animal:
    def make_sound(self):
        return "Some generic sound"

class Canine(Animal):
    def make_sound(self):
        return "Canine sound"

class Dog(Canine):
    def make_sound(self):
        return "Bark"

# Checking the MRO
print(Dog.mro())  # Output: [<class '__main__.Dog'>, <class '__main__.Canine'>, <class '__main__.Animal'>, <class 'object'>]

# Creating an object of Dog and calling make_sound
dog = Dog()
print(dog.make_sound())  # Output: Bark

In this example:

The MRO ensures that Python searches for methods in the subclass Dog, then Canine, and then Animal.
Dog.mro() returns the MRO list, showing the order in which methods are resolved.

7. Inheritance of Class Methods and Static Methods

Inheritance applies not only to instance methods but also to class methods and static methods. Subclasses can inherit and override both types of methods.

Example: Inheriting Class Methods and Static Methods

# Example: Inheriting class and static methods
class Animal:
    @classmethod
    def category(cls):
        return "Mammal"

    @staticmethod
    def general_info():
        return "Animals are multicellular organisms."

class Dog(Animal):
    @classmethod
    def category(cls):
        return "Canine"

# Accessing class method and static method from the subclass
print(Dog.category())      # Output: Canine (overridden)
print(Dog.general_info())  # Output: Animals are multicellular organisms. (inherited)

In this example:

The Dog class overrides the category() class method but inherits the general_info() static method from the Animal class.

8. Abstract Classes and Inheritance

Python supports abstract classes, which are classes that cannot be instantiated directly. Abstract classes are typically used to define a common interface for subclasses to implement. You can create abstract classes using the abc module.

Example: Abstract Classes and Inheritance

# Example: Abstract classes and inheritance
from abc import ABC, abstractmethod

class Animal(ABC):
    @abstractmethod
    def make_sound(self):
        pass

class Dog(Animal):
    def make_sound(self):
        return "Bark"

# Creating an object of Dog class (abstract methods must be implemented)
dog = Dog()
print(dog.make_sound())  # Output: Bark

# Trying to instantiate an abstract class will raise an error
# animal = Animal()  # TypeError: Can't instantiate abstract class Animal with abstract method make_sound

In this example:

The Animal class is an abstract class that defines the make_sound() method as abstract.
The Dog class inherits from Animal and implements the make_sound() method. The abstract class cannot be instantiated directly.

Summary

Inheritance allows a subclass to inherit attributes and methods from a parent class, enabling code reuse and specialization.
Subclasses can override methods to provide specific implementations, and super() can be used to call methods from the parent class.
Python supports multiple inheritance, where a subclass can inherit from more than one parent class.
You can use isinstance() and issubclass() to check relationships between objects and classes in an inheritance hierarchy.
Method Resolution Order (MRO) determines the order in which methods are resolved when multiple inheritance is involved.
Both class methods and static methods can be inherited and overridden in subclasses.
Abstract classes define a common interface for subclasses and must be subclassed and implemented before instantiation.

By mastering inheritance in Python, you can design more flexible, reusable, and modular code, which is essential for object-oriented programming.

You may also like

Leave a Comment

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More