Python Inheritance and Polymorphism: The Complete Beginner's Guide
Day 12 builds on classes and objects with inheritance, \`super()\`, overriding, polymorphism, abstract base classes, MRO, and mixins - so your code scales without duplication.
Chapter 12 of 20 · Intermediate · 50 min · Python Programming Course
In Day 11 you learned how to create classes that bundle data and behaviour into coherent objects. Every class you wrote started from scratch - defining every attribute and method independently.
But most real-world concepts share structure. Inheritance lets you define shared parts once in a parent class, while child classes add or change only what is unique.
Polymorphism takes this further: one interface, many implementations. Code can work with objects by behavior rather than concrete type.
What You Will Learn in This Chapter
By the end of this tutorial you will be able to:
- Create child classes that inherit from parent classes
- Override parent methods with child-specific behaviour
- Use
super()to extend parent behaviour safely - Write child
__init__methods correctly - Apply single and multiple inheritance
- Use
isinstance()andissubclass() - Write polymorphic code across multiple types
- Create abstract base classes using
abc - Use mixins for reusable cross-cutting behaviour
- Choose between inheritance and composition
- Avoid common inheritance mistakes
Estimated time: 50 minutes reading + 25 minutes practice
The Problem Inheritance Solves
# Without inheritance - duplicated fields and methods
class CreditCardPayment:
def __init__(self, amount, currency, card_number):
self.amount = amount
self.currency = currency
self.card_number = card_number
self.status = "pending"
def validate(self):
return self.amount > 0
def get_receipt(self):
return f"Payment of {self.amount} {self.currency} - {self.status}"
class Payment:
def __init__(self, amount, currency):
self.amount = amount
self.currency = currency
self.status = "pending"
def validate(self):
return self.amount > 0
def get_receipt(self):
return f"Payment of {self.amount} {self.currency} - {self.status}"
class CreditCardPayment(Payment):
def __init__(self, amount, currency, card_number):
super().__init__(amount, currency)
self.card_number = card_number
Shared behavior now lives in one place.
Basic Inheritance Syntax
class Parent:
def greet(self):
return "Hello from Parent"
class Child(Parent):
pass
super() - Extending Parent Behaviour
super() delegates to the next class in MRO. Most commonly used in child __init__:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
class Employee(Person):
def __init__(self, name, age, company):
super().__init__(name, age)
self.company = company
Use super() in regular methods too when you want to extend parent logic.
Method Overriding
Overriding replaces a parent method implementation in a child:
class Shape:
def area(self):
return 0
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
Polymorphism - One Interface, Multiple Implementations
class Notification:
def send(self):
raise NotImplementedError
class EmailNotification(Notification):
def __init__(self, message, email):
self.message = message
self.email = email
def send(self):
return f"Email to {self.email}: {self.message}"
class SMSNotification(Notification):
def __init__(self, message, phone):
self.message = message
self.phone = phone
def send(self):
return f"SMS to {self.phone}: {self.message}"
def send_all(notifications):
for n in notifications:
print(n.send())
isinstance() and issubclass()
class Animal: pass
class Dog(Animal): pass
dog = Dog()
print(isinstance(dog, Dog)) # True
print(isinstance(dog, Animal)) # True
print(issubclass(Dog, Animal)) # True
Abstract Base Classes
Use abc to enforce required methods:
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
A subclass missing an abstract method cannot be instantiated.
Multiple Inheritance and MRO
Python supports multiple inheritance and resolves methods via MRO:
class A:
def hello(self):
return "A"
class B(A):
def hello(self):
return "B"
class C(A):
def hello(self):
return "C"
class D(B, C):
pass
print(D().__mro__)
print(D().hello()) # B
Mixins
Mixins add reusable capabilities across unrelated classes:
class LogMixin:
def log(self, message):
print(f"[{self.__class__.__name__}] {message}")
class ValidationMixin:
def is_positive(self, value, field_name):
if value <= 0:
raise ValueError(f"{field_name} must be positive")
Inheritance vs Composition
- Use inheritance for true "is-a" relationships.
- Use composition for "has-a" relationships.
If "Child IS A Parent" sounds wrong, composition usually wins.
A Complete Working Program
Employee system using abstract class + mixin + polymorphism:
from abc import ABC, abstractmethod
class AuditMixin:
def __init__(self):
self._audit_log = []
def _record(self, action):
self._audit_log.append(action)
def get_audit_log(self):
return self._audit_log.copy()
class Employee(AuditMixin, ABC):
employee_count = 0
def __init__(self, name, employee_id, base_salary):
super().__init__()
self.name = name
self.employee_id = employee_id
self.base_salary = base_salary
self._performance_rating = 3
Employee.employee_count += 1
self._record(f"Employee {name} created")
@abstractmethod
def calculate_bonus(self):
pass
class Engineer(Employee):
def calculate_bonus(self):
return int(self.base_salary * 0.12)
class Contractor(Employee):
def calculate_bonus(self):
return 0
This demonstrates extensible design with shared contracts and type-specific behavior.
5 Inheritance Mistakes Every Beginner Makes
- Forgetting
super().__init__()in child constructors - Rewriting parent behavior instead of extending with
super() - Creating deep, fragile inheritance chains
- Using inheritance without a true "is-a" relationship
- Forgetting abstract method implementations
Practice: Inheritance and Polymorphism Exercises
- Vehicle parent with Car/Truck children
- Abstract Animal class with Dog/Cat/Fish/Bird
- Person -> Student/Teacher with
super() - Serialize mixin for Product and Customer
- Report ABC with SalesReport/InventoryReport/UserReport
-> See all Python OOP exercises with solutions
What Comes Next - Day 13: Modules and Packages
Next chapter covers:
- Creating and importing modules
import,from ... import,as- Standard library usage
- Installing packages with pip
- Building packages with
__init__.py - Avoiding circular imports
-> Continue to Day 13: Modules and Packages
Frequently Asked Questions
What is inheritance in Python?
Inheritance allows a child class to automatically receive attributes and methods from a parent class.
What does super() do in Python?
super() resolves and calls parent behavior according to MRO, commonly used for parent initialization.
What is method overriding in Python?
A child class defines a method with the same name as a parent to provide specialized behavior.
What is polymorphism in Python?
The same method call behaves differently across object types that share an interface.
What is an abstract class in Python?
A class that defines required methods via @abstractmethod, enforcing an interface contract.
What is the Method Resolution Order (MRO) in Python?
The order Python uses to search classes for methods/attributes, available via Class.__mro__.
When should I use inheritance vs composition?
Use inheritance for "is-a". Use composition for "has-a".
What is a mixin in Python?
A small class that contributes reusable capability to other classes via inheritance.
Chapter navigation
- Previous: Day 11: Classes and Objects
- Next: Day 13: Modules and Packages
- Python Quiz: Take the Python quiz
- All Python exercises: Explore Python exercises
Frequently asked questions: Inheritance and polymorphism
What is inheritance in Python?
Inheritance allows a child class to automatically receive attributes and methods from a parent class, then extend or override behavior.
What does super() do in Python?
super() returns a proxy to parent behavior according to MRO, commonly used to call parent __init__ and extend parent methods safely.
What is method overriding in Python?
Method overriding happens when a child class defines a method with the same name as the parent, replacing behavior for child instances.
What is polymorphism in Python?
Polymorphism means one interface, many implementations: the same method call works across different object types.
What is an abstract class in Python?
An abstract class, built with ABC and @abstractmethod, defines required methods that subclasses must implement before instantiation.
What is the Method Resolution Order (MRO) in Python?
MRO is the order Python uses to resolve attributes and methods in inheritance hierarchies, especially with multiple inheritance.
When should I use inheritance vs composition?
Use inheritance for true is-a relationships. Use composition for has-a relationships where one class contains or delegates to another.
What is a mixin in Python?
A mixin is a lightweight class that adds reusable capability (like logging or serialization) to unrelated classes via inheritance.
Related Page
Day 11: Classes and Objects
Learn about day 11: classes and objects
Learn MoreDay 13: Modules and Packages
Continue with day 13: modules and packages
Learn MorePython exercises hub
165+ programs with solutions
Learn MorePython quiz
Multiple-choice checks with explanations
Learn MorePython OOP programs
Inheritance and polymorphism practice programs
Learn More