Inheritance

One class taking another's behaviour, overriding part of it, and calling back into the parent with super().

Overview

The basic move

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

Dog gets everything Animal has. Where it defines a method of the same name, that version wins — that is overriding.

The payoff shows up in methods the parent already wrote:

def describe(self):
    return f"{self.name} says {self.speak()}"

describe was written once on Animal and calls whichever speak the actual object has. Add a tenth animal and describe needs no change. That is the whole argument for inheritance in one method.

inheritance.py

inheritance.py Python 3
Output

                    

super_and_mro.py

super_and_mro.py Python 3
Output

                    

Worth knowing

class Dog(Animal) gives Dog everything Animal has, before Dog adds anything.
Defining a method with the same name overrides it; the parent's version is still reachable with super().
A subclass __init__ should call super().__init__(...) or the parent's setup never runs.
Prefer composition when the relationship is "has a" rather than "is a".

Inheritance: A Practical Guide

A class can be built on another one, taking its attributes and methods and changing only what differs. Used carefully it removes real duplication; used loosely it produces hierarchies nobody can follow.

super()

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)
        self.breed = breed

A subclass __init__ replaces the parent's, so the parent's setup does not happen unless you ask for it. Forget super().__init__(name) and self.name never gets set — the failure arrives later as an AttributeError from some unrelated method, which the page demonstrates.

super() also works for extending rather than replacing:

return super().speak().upper() + "!!!"

Take the parent's answer, then modify it.

The lookup order

With several parents, Python walks a defined order — the MRO, visible as Cls.__mro__ — taking the first match. Reading it is how you answer "which version actually ran".

Multiple inheritance is a sharp tool. Mixins with distinct responsibilities are fine; deep diamond hierarchies are how codebases become unreadable.

is-a, not has-a

Inherit when the subclass genuinely is a kind of the parent and can be used wherever the parent is expected. A Dog is an Animal, so describe works on both.

When the relationship is "has a" — a Car has an Engine — hold the other object as an attribute instead. Composition is easier to change later, because it does not tie two classes together permanently to share a couple of methods.

The common failure is inheriting to reuse a method. If that is the only reason, a function or a held object is nearly always the better answer.

Check yourself

0 of 3

Answer without scrolling back up.

  1. What happens if a subclass __init__ does not call super().__init__()?

  2. Why can `describe()` on the parent call the child's `speak()`?

  3. A Car has an Engine. Should Car inherit from Engine?

Cheat sheet

Inheritance

A class can be built on another one, taking its attributes and methods and changing only what differs. Used carefully it removes real duplication; used loosely it produces hierarchies nobody can follow.

PYTHON · vizlearn.in/python/inheritance.html

About the author

Ashish Jangra builds and maintains VizLearn. Every module here is written and the visualisation behind it hand-built, so the numbers in a readout come from the same code that draws the picture. Corrections are genuinely welcome and get priority over everything else — if a page states something wrong, or an animation misrepresents what the algorithm does, get in touch.