Inheritance

Create extensible class hierarchies, reuse behavior safely, and design APIs that stay flexible as your codebase grows.

Learn Python, JavaScript, Java and more with free interactive lessons, real projects and AI-powered help. Beginner-friendly.

Part of the free Python course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

What You'll Learn in This Lesson

Think of a family tree . Children inherit traits from their parents (eye color, height) but can also have their own unique traits. In programming, a child class inherits features from a parent class but can add or change behaviors.

Polymorphism means "many forms": different classes expose the same method name but implement it differently, so your high-level code doesn't care which concrete type it's using—only that it supports the interface.

💡 Why This Matters: This improves extensibility , testability , and readability in real projects like games, APIs, and data pipelines.

✨ Key Point: The child inherits ALL attributes and methods from the parent. You can then override (replace) or extend (add to) them.

super() is a special function that gives you access to the parent class . It's like saying "Hey, parent class, please run YOUR version of this method first!"

Override to change behavior; extend to add extra steps:

A smartphone inherits features from both a phone AND a camera . That's multiple inheritance—one class getting abilities from multiple parents!

Rule of thumb: Favor composition over inheritance unless the IS-A relation is obvious and stable.

"If it walks like a duck and quacks like a duck, it's a duck!"

In Python, we don't care what type an object is—we only care what it can do . If it has a .speak() method, we can call it!

✨ Key Insight: This is duck typing in action! Python is flexible—it doesn't need formal interfaces or shared parents.

An abstract class is like a template or contract . It says "any class that inherits from me MUST implement these methods" but doesn't provide the implementation itself.

With type hints you can express "any object with .area() is acceptable"—even if it doesn't inherit from Shape.

This is powerful for plug-in systems and testing.

If you have code that works with Animal , it should also work with Dog or Cat without any surprises. A child class should behave like its parent, not break expectations.

💡 Rule of Thumb: If you need to check "is this a Dog or a Cat?" before calling a method, you might be violating LSP. Good polymorphism means you don't need to check!

Composition is easier to refactor and avoids MRO tangles.

A mixin is a parent with only helper behavior, no standalone identity.

Use mixins sparingly, name them *Mixin , and avoid shared state.

Special methods let your classes participate in Python's operators—another form of polymorphism.

No inheritance required, but you still get clean polymorphism. If you later need guarantees, move to an ABC/Protocol.

All classes call super() with **kw , so init flows through the MRO smoothly.

📋 Quick Reference — Inheritance

You now understand inheritance, method overriding, super(), MRO, and polymorphism — the tools that make Python class hierarchies clean and extensible.

Up next: Decorators & Advanced Features — learn to wrap functions with reusable behaviour using Python's elegant decorator syntax.

Practice quiz

How do you make class Dog inherit from class Animal?

  • class Dog -> Animal:
  • class Dog inherits Animal:
  • class Dog(Animal):
  • class Dog extends Animal:

Answer: class Dog(Animal):. Python uses parentheses: class Dog(Animal): puts the parent class inside the parentheses.

Inside a child's __init__, how do you call the parent class's __init__?

  • super().__init__(name)
  • parent.__init__(name)
  • Animal.init(name)
  • self.super(name)

Answer: super().__init__(name). super().__init__(name) runs the parent constructor so its setup (like self.name) actually happens.

What does Duck.mro() return for class Duck(Walker, Swimmer)?

  • Walker
  • Swimmer
  • Duck

The MRO lists Duck first, then parents left-to-right (Walker, Swimmer), then object.

What does the @abstractmethod decorator (from abc) enforce?

  • The method runs automatically
  • Child classes must implement that method
  • The method becomes static
  • The method is cached

Answer: Child classes must implement that method. An abstractmethod is a promise: any concrete subclass must implement it, or instantiation fails.

What is 'duck typing' in Python?

  • Caring only about whether an object has the needed method, not its type
  • Requiring all objects to share a parent class
  • A way to copy ducks
  • Strict compile-time type checking

Answer: Caring only about whether an object has the needed method, not its type. Duck typing: if it has .speak(), you can call it — Python checks behavior, not the exact type.

Given Vector2 with __add__ defined, what does Vector2(1, 2) + Vector2(3, 4) produce?

  • Vector2(3, 8)
  • Vector2(1, 2, 3, 4)
  • Vector2(4, 6)
  • a TypeError

Answer: Vector2(4, 6). __add__ adds component-wise: x=1+3=4, y=2+4=6, giving Vector2(4, 6).

An abstract base class created with abc.ABC and an abstractmethod...

  • can be instantiated directly
  • cannot be instantiated directly
  • has no methods
  • must inherit from object explicitly

Answer: cannot be instantiated directly. Abstract classes act as templates/contracts and cannot be instantiated directly.

Which relationship signals you should prefer composition over inheritance?

  • IS-A (Dog is an Animal)
  • Any 2-level hierarchy
  • Polymorphic methods
  • HAS-A (Car has an Engine)

Answer: HAS-A (Car has an Engine). A HAS-A relationship (a Car has an Engine) is best modeled with composition, not inheritance.

The Liskov Substitution Principle (LSP) says a subclass should...

  • always add new attributes
  • be usable anywhere its parent is expected, without surprises
  • never override methods
  • require stricter inputs than the parent

Answer: be usable anywhere its parent is expected, without surprises. LSP: code that works with the parent type should work with any subclass without breaking expectations.

What is a mixin?

  • A class that cannot be subclassed
  • A function decorator
  • A small parent that adds focused behavior, with no standalone identity
  • A way to merge two instances

Answer: A small parent that adds focused behavior, with no standalone identity. A mixin is a small, behavior-only parent (named *Mixin) you mix in to add reusable functionality.