Course topics

By WebNest Studio

Python Tutorial

Inheritance in Python

Inheritance lets a new class reuse and extend an existing one. A SavingsAccount is a BankAccount with interest; an Admin is a User with extra permissions. The new class (child, subclass) inherits the attributes and methods of the existing class (parent, base, superclass) and can add or override behaviour.

This lesson covers single, multilevel, hierarchical and multiple inheritance, super(), method overriding, the Method Resolution Order (MRO), isinstance/issubclass, and mixins.

Single Inheritance and Overriding

class Child(Parent): creates a subclass. The child inherits everything; defining a method with the same name overrides the parent's. Inside the override, super().method() calls the parent version so you extend rather than replace behaviour. Every class ultimately inherits from object.

Types of Inheritance

The common structures:

  • Single — one parent: Dog(Animal).
  • Multilevel — a chain: Puppy(Dog), Dog(Animal).
  • Hierarchical — several children of one parent: Dog(Animal), Cat(Animal).
  • Multiple — several parents: FlyingCar(Car, Aircraft).
  • Hybrid — a combination of the above.

Multiple Inheritance and the MRO

With several parents, Python searches for attributes in the Method Resolution Order, computed by the C3 linearisation algorithm and visible in Class.__mro__ or Class.mro(). super() follows the MRO, not simply "the parent", which lets cooperative classes each run once even in diamond-shaped hierarchies.

Mixins

A mixin is a small class that adds one capability (serialisation to JSON, logging, comparison) and is designed to be combined with others through multiple inheritance: class Order(JsonMixin, TimestampMixin, Model). Mixins should not have their own __init__ state requirements.

Examples

Single inheritance, overriding and super()

Python
class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner, self.balance = owner, balance

    def describe(self):
        return f"{self.owner}: Rs.{self.balance}"

    def month_end(self):
        pass

class SavingsAccount(BankAccount):
    def __init__(self, owner, balance=0, rate=0.04):
        super().__init__(owner, balance)
        self.rate = rate

    def month_end(self):                       # override
        self.balance += round(self.balance * self.rate / 12, 2)

    def describe(self):                        # extend
        return super().describe() + f" (savings @ {self.rate:.0%})"

acc = SavingsAccount("Asha", 12000)
acc.month_end()
print(acc.describe())
print(isinstance(acc, BankAccount), issubclass(SavingsAccount, BankAccount))
Output
Asha: Rs.12040.0 (savings @ 4%)
True True

Multilevel and hierarchical inheritance

Python
class Animal:
    def __init__(self, name):
        self.name = name
    def speak(self):
        return "..."
    def intro(self):
        return f"{self.name} says {self.speak()}"

class Dog(Animal):
    def speak(self):
        return "Woof"

class Puppy(Dog):
    def speak(self):
        return super().speak() + " (tiny)"

class Cat(Animal):
    def speak(self):
        return "Meow"

for pet in [Dog("Rex"), Puppy("Bolt"), Cat("Tom"), Animal("Generic")]:
    print(pet.intro())
print([c.__name__ for c in Puppy.__mro__])
Output
Rex says Woof
Bolt says Woof (tiny)
Tom says Meow
Generic says ...
['Puppy', 'Dog', 'Animal', 'object']

Multiple inheritance, the diamond and the MRO

Python
class Base:
    def setup(self):
        print("Base.setup")

class Logging(Base):
    def setup(self):
        print("Logging.setup")
        super().setup()

class Caching(Base):
    def setup(self):
        print("Caching.setup")
        super().setup()

class Service(Logging, Caching):
    def setup(self):
        print("Service.setup")
        super().setup()

Service().setup()
print([c.__name__ for c in Service.mro()])
Output
Service.setup
Logging.setup
Caching.setup
Base.setup
['Service', 'Logging', 'Caching', 'Base', 'object']

A mixin adding JSON serialisation

Python
import json

class JsonMixin:
    def to_json(self):
        return json.dumps(vars(self), sort_keys=True)

class Course:
    def __init__(self, title, lessons):
        self.title, self.lessons = title, lessons

class PublishedCourse(JsonMixin, Course):
    pass

print(PublishedCourse("Python", 130).to_json())
Output
{"lessons": 130, "title": "Python"}

Common Mistakes

  • Forgetting to call super().__init__() in a subclass constructor.
  • Calling Parent.method(self) directly in multiple inheritance, which can run a base class twice; use super().
  • Deep inheritance hierarchies that are hard to follow — prefer composition for "has-a" relationships.
  • Inheriting just to reuse one helper method.

Key Points to Remember

  • class Child(Parent) inherits attributes and methods; overriding replaces them.
  • super() calls the next class in the MRO, letting you extend behaviour.
  • Python supports single, multilevel, hierarchical, multiple and hybrid inheritance.
  • The MRO (Class.__mro__) defines lookup order in multiple inheritance.
  • Mixins add focused capabilities through multiple inheritance.

Practice the examples

Change an input, predict the result, then compare it with the output. Explain why the result changes.