Inheritance in Python

Inheritance is a mechanism that allows you to create a new class based on an existing one. The child class receives the attributes and methods of the parent class, but can extend and modify this functionality.

Simply put, inheritance represents an "is-a" relationship: a dog is an animal, a passenger car is a vehicle.

Why is inheritance needed?

  • 🔄 Code reuse — eliminates duplication
  • 🌲 Logical hierarchies — reflects natural relationships between objects
  • 🧩 Extensibility — easy to add new functionality
  • 🔄 Polymorphism — use objects of different classes uniformly

Simple Inheritance in Python

Creating a child class in Python is very simple — you need to specify the parent class in parentheses:

Python 3.13
# Base class
>>> class Animal:
...     def __init__(self, name):
...         self.name = name

>>>     def speak(self):
...         return "Animal sound"

# Child class
>>> class Dog(Animal):  # Dog inherits from Animal
...     def speak(self):  # Override the method
...         return f"{self.name} says: Woof!"

# Create instances
>>> animal = Animal("Creature")
>>> dog = Dog("Rex")

# Call methods
>>> print(animal.speak())
Animal sound
>>> print(dog.speak()) # Calls the overridden method
Rex says: Woof!
>>> print(dog.name) # Attribute inherited from the parent class
Rex

Calling Parent Class Methods with super()

Often you need to extend the functionality of a parent method rather than completely replace it. For this, the super() function is used:

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

>>>     def info(self):
...         return f"Vehicle brand {self.brand}"

>>> class Car(Vehicle):
...     def __init__(self, brand, model):
...         super().__init__(brand)  # Call the parent's constructor
...         self.model = model

>>>     def info(self):
...         # Extend the parent method
...         return f"{super().info()}, model {self.model}"

# Create a car
>>> car = Car("Toyota", "Corolla")
>>> print(car.info())
Vehicle brand Toyota, model Corolla

Inheritance Hierarchies

Inheritance can be arranged in multi-level hierarchies:

Python 3.13
>>> class Animal:
...     def eat(self):
...         return "Animal eats"

>>> class Mammal(Animal):
...     def breathe(self):
...         return "Breathes with lungs"

>>> class Dog(Mammal):
...     def bark(self):
...         return "Woof!"

# Create a dog
>>> dog = Dog()
>>> print(dog.eat())    # Method from Animal
Animal eats
>>> print(dog.breathe()) # Method from Mammal
Breathes with lungs
>>> print(dog.bark()) # Method from Dog
Woof!

Checking Inheritance: isinstance() and issubclass()

Python provides useful functions for checking inheritance relationships:

Python 3.13
# Base class - parent in the hierarchy
>>> class Vehicle:
...     pass  # Empty class for demonstrating inheritance

# Child classes - inherit from Vehicle
>>> class Car(Vehicle):
...     pass  # Car is a type of Vehicle

>>> class Bicycle(Vehicle):
...     pass  # Bicycle is also a type of Vehicle

# Create objects
>>> car = Car()  # Instance of the Car class
>>> bicycle = Bicycle()  # Instance of the Bicycle class

# Check object types
# Is car an instance of the Car class?
>>> print(isinstance(car, Car))
True
# Is car an instance of the Vehicle class (through inheritance)? >>> print(isinstance(car, Vehicle))
True
# Is car an instance of the Bicycle class? >>> print(isinstance(car, Bicycle))
False
# Check relationships between classes >>> print(issubclass(Car, Vehicle)) # Is Car a subclass of Vehicle?
True
>>> print(issubclass(Vehicle, Car)) # Is Vehicle a subclass of Car?
False

Abstract Classes

Abstract classes serve as templates for creating other classes. They contain abstract methods that must be implemented in subclasses:

Python 3.13
>>> from abc import ABC, abstractmethod

>>> class Shape(ABC):  # Abstract class
...     @abstractmethod
...     def area(self):
...         pass

>>>     @abstractmethod
...     def perimeter(self):
...         pass

>>> class Rectangle(Shape):
...     def __init__(self, width, height):
...         self.width = width
...         self.height = height

>>>     def area(self):
...         return self.width * self.height

>>>     def perimeter(self):
...         return 2 * (self.width + self.height)

# Attempt to create an instance of an abstract class
>>> try:
...     shape = Shape()
... except TypeError as e:
...     print(f"Error: {e}")
Error: Can't instantiate abstract class Shape with abstract methods area, perimeter
# Creating an instance of a concrete class >>> rect = Rectangle(5, 3) >>> print(f"Area: {rect.area()}")
Area: 15
>>> print(f"Perimeter: {rect.perimeter()}")
Perimeter: 16

Multiple Inheritance

Python supports multiple inheritance, where a class inherits from several parents:

Python 3.13
>>> class Flying:
...     def fly(self):
...         return "I can fly!"

>>> class Swimming:
...     def swim(self):
...         return "I can swim!"

# Multiple inheritance
>>> class Duck(Flying, Swimming):
...     def sound(self):
...         return "Quack!"

# Create a duck
>>> duck = Duck()
>>> print(duck.fly())
I can fly!
>>> print(duck.swim())
I can swim!
>>> print(duck.sound())
Quack!

Method Resolution Order (MRO)

With multiple inheritance, it's important to know in what order Python searches for methods in classes. This order is called Method Resolution Order (MRO):

Python 3.13
>>> class A:
...     def method(self):
...         return "A"

>>> class B(A):
...     def method(self):
...         return "B"

>>> class C(A):
...     def method(self):
...         return "C"

>>> class D(B, C):
...     pass

# Check the MRO of class D
>>> print(D.__mro__)
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
# Create an object and call the method >>> d = D() >>> print(d.method()) # The method from B will be called, as B comes before C
B

Understanding Check

What happens when a method is called from a child class that doesn't override this method of the parent class?


We are in touch with you
English