Once you start writing classes, you'll notice that some of them are variations of each other. A savings account is an account that also earns interest. A cat and a dog are both animals with a name and an age, but they make different sounds. Copying the shared code into each class would work, but then every fix has to be made in several places.
Inheritance solves this. A new class, the child or subclass, can be built on top of an existing parent class. It automatically gets all of the parent's attributes and methods, and it can add new ones or replace, called override, the ones that need to behave differently.
In this lesson you'll create subclasses, extend __init__ with super(), override methods, and see how polymorphism lets one piece of code work with many related types. You'll also learn when inheritance is the wrong tool, which matters just as much.
Creating a subclass
Put the parent class in brackets after the child's name:
class Animal:
def __init__(self, name):
self.name = name
def describe(self):
return f"{self.name} is an animal"
class Dog(Animal):
def speak(self):
return "Woof"Dog has no __init__ or describe() of its own, yet Dog("Rex").describe() works, because it inherits them from Animal. It also adds a new method, speak(), that plain animals don't have. Read class Dog(Animal) as "a Dog is an Animal".
Overriding methods and super()
If a child defines a method with the same name as one in the parent, the child's version is used instead. That's overriding.
Often you want to extend the parent's behaviour rather than replace it completely. super() gives you access to the parent's version:
class SavingsAccount(Account):
def __init__(self, owner, balance=0, rate=0.03):
super().__init__(owner, balance) # let Account set owner and balance
self.rate = rate # then add what's newCalling super().__init__(...) first is the usual pattern. It runs the parent's set-up code, so you don't repeat it, and then the child adds its own attributes.
Multiple inheritance and the MRO
A Python class can inherit from more than one parent: class FlyingCar(Car, Aircraft):. When the same method exists in several ancestors, Python decides which one to use by following the method resolution order (MRO), a single fixed list of classes it checks in turn. You can print it:
class A:
def hello(self):
return "A"
class B(A):
pass
class C(A):
def hello(self):
return "C"
class D(B, C):
pass
print([cls.__name__ for cls in D.__mro__]) # ['D', 'B', 'C', 'A', 'object']
print(D().hello()) # CD doesn't define hello, neither does B, so Python finds it in C before reaching A. super() follows the same order, which is why it is safer than naming the parent class directly. In everyday code, multiple inheritance is mostly used for small mixin classes that add one capability, such as logging or JSON export.
Polymorphism
Polymorphism means "many forms": different classes provide the same method, each in its own way, and your code can call it without caring which class it's dealing with.
for animal in [Dog("Rex"), Cat("Tom"), Cow("Daisy")]:
print(animal.speak())The loop doesn't check types or use a long if. Each object knows how to speak(). Adding a new animal later only means writing a new class; the loop doesn't change. This is one of the main benefits of object-oriented design.
isinstance() and composition
isinstance(obj, Class) checks whether an object is an instance of a class or any of its subclasses: isinstance(Dog("Rex"), Animal) is True. issubclass(Dog, Animal) checks the classes themselves.
Inheritance isn't always the answer. If the relationship is "has a" rather than "is a", use composition: give one object another object as an attribute. A car has an engine, so a Car should store an Engine object, not inherit from Engine. Composition keeps classes small and flexible, and many experienced developers prefer it unless there's a clear "is a" relationship.
Python Inheritance Syntax
Inheritance syntax
class Parent:
def __init__(self, a):
self.a = a
def method(self):
return "parent"
class Child(Parent):
def __init__(self, a, b):
super().__init__(a)
self.b = b
def method(self): # override
return "child + " + super().method()Python Inheritance Summary
class Child(Parent):makes a subclass that inherits the parent's attributes and methods.- Defining a method with the same name overrides the parent's version.
super().__init__(...)runs the parent's set-up before the child adds its own.- Polymorphism lets code call the same method on different classes.
isinstance()checks types including subclasses; prefer composition for "has a" relationships.
Python Inheritance Examples
Each example shows the code, the output it produces and what each part does.
Animals that speak differently
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return "..."
def introduce(self):
return f"{self.name} says {self.speak()}"
class Dog(Animal):
def speak(self):
return "Woof"
class Cat(Animal):
def speak(self):
return "Meow"
for pet in [Dog("Rex"), Cat("Tom"), Animal("Mystery")]:
print(pet.introduce())Rex says Woof
Tom says Meow
Mystery says ...Line-by-line explanation
- Lines 8 to 9introduce() is written once, in the parent class.
- Lines 11 to 17Each subclass only overrides speak().
- Lines 19 to 20Polymorphism: the same call gives different results for each class.
Extending a class with super()
class Account:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def __str__(self):
return f"{self.owner}: £{self.balance:.2f}"
class SavingsAccount(Account):
def __init__(self, owner, balance=0, rate=0.05):
super().__init__(owner, balance)
self.rate = rate
def add_interest(self):
self.balance += self.balance * self.rate
def __str__(self):
return super().__str__() + f" (saving at {self.rate:.0%})"
s = SavingsAccount("Priya", 200)
s.add_interest()
print(s)
print(isinstance(s, Account))Priya: £210.00 (saving at 5%)
TrueLine-by-line explanation
- Line 11The parent sets owner and balance, so that code isn't repeated.
- Lines 14 to 15A method only savings accounts have.
- Lines 17 to 18Extend the parent's __str__ instead of rewriting it. :.0% shows 0.05 as 5%.
- Line 23A SavingsAccount is also an Account.
Composition: a car has an engine
class Engine:
def __init__(self, horsepower):
self.horsepower = horsepower
def start(self):
return f"{self.horsepower} hp engine running"
class Car:
def __init__(self, model, engine):
self.model = model
self.engine = engine
def drive(self):
return f"{self.model}: {self.engine.start()}"
city_car = Car("Mini", Engine(90))
print(city_car.drive())Mini: 90 hp engine runningLine-by-line explanation
- Line 11The car stores an Engine object as one of its attributes.
- Line 14The car asks its engine to do its part, instead of inheriting from it.
Common Python Inheritance Mistakes
Forgetting to call super().__init__
class SavingsAccount(Account):
def __init__(self, owner, rate):
self.rate = rate
s = SavingsAccount("Priya", 0.05)
print(s.owner) # AttributeError: no attribute 'owner'class SavingsAccount(Account):
def __init__(self, owner, rate):
super().__init__(owner)
self.rate = rateInheriting when it should be "has a"
class Car(Engine):
passclass Car:
def __init__(self, engine):
self.engine = engineA car isn't a kind of engine; it has one.
Checking types instead of using polymorphism
for a in animals:
if type(a) == Dog:
print("Woof")
elif type(a) == Cat:
print("Meow")for a in animals:
print(a.speak())Python Inheritance in Real Projects
Inheritance in real projects
In Django, every database model inherits from models.Model, which gives it saving, deleting and querying without any extra code. Python's own exceptions form an inheritance tree, which is why catching Exception also catches ValueError. Game engines often have a base Sprite class with movement and drawing, extended by players, enemies and items.
Python Inheritance FAQ
What is the difference between overriding and overloading in Python?
Overriding means a subclass replaces a method it inherited, keeping the same name. Overloading means several methods with the same name but different parameters, which Python does not support directly: a later def with the same name simply replaces the earlier one. Python uses default and keyword arguments for the same purpose.
Do I always need to call super().__init__()?
Call it whenever the parent's __init__ sets up attributes the child relies on, which is almost always. If the child defines no __init__ at all, the parent's runs automatically. Forgetting the call when the child does define __init__ leaves the parent's attributes missing and causes AttributeError later.
Does every Python class inherit from something?
Yes. Every class ultimately inherits from the built-in object, even if you write class Dog: with no brackets. That is where default methods such as __str__, __repr__ and __eq__ come from.
When should I use composition instead of inheritance?
Use inheritance when the child truly is a specialised kind of the parent and can be used anywhere the parent is expected. Use composition when one object simply uses another, such as a car that has an engine. If you need to override or disable much of the parent, composition is usually the better design.
What is an abstract base class?
It is a parent class that defines methods its subclasses must implement and can't be instantiated itself. In Python you create one with the abc module: inherit from ABC and mark methods with @abstractmethod. Subclasses that don't implement every abstract method raise a TypeError when you try to create them.
Python Inheritance Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Complete the line so Truck inherits from Vehicle.
class Truck():
pass
Complete the constructor so the parent sets up the name first.
class Student(Person):
def __init__(self, name, school):
().__init__(name)
self.school = school
What does this print?
class A:
def hello(self):
return "A"
class B(A):
def hello(self):
return "B" + super().hello()
print(B().hello())
What does this print?
class Shape: pass
class Square(Shape): pass
print(isinstance(Square(), Shape), isinstance(Shape(), Square))
A Library contains many Book objects. How should you model it?
Python Inheritance Quiz
5 questions to check what you learned.
What does a subclass inherit from its parent?
- Nothing
- Only its __init__
- Its attributes and methods
- Only methods named with underscores
What is method overriding?
- Deleting a parent method
- Defining a method in the child with the same name as one in the parent
- Calling a method twice
- Making a method private
What does
super().__init__(name)do inside a child's__init__?- Creates a second object
- Deletes the parent's attributes
- Calls the child's __init__ again
- Runs the parent class's __init__ for this object
What is polymorphism?
- Different classes responding to the same method call in their own way
- A class with many attributes
- A class that inherits from many parents
- Changing an object's type
When is composition usually better than inheritance?
- When the relationship is "is a"
- When there are no methods
- Never
- When the relationship is "has a"