Every dog is an animal — so a Dog class should not redefine breathing from scratch. Inheritance lets a child class automatically receive all the attributes and methods of its parent class, adding only what makes it unique. It is the programming equivalent of biological inheritance: children share traits with parents but develop their own too.
What is inheritance and why does it matter?
Inheritance allows a class (the child or subclass) to take on all the attributes and methods of another class (the parent or superclass), without the programmer having to copy any code.
This achieves three important goals:
- Code reuse — shared behaviour is written once in the parent and used automatically by all children.
- Consistency — all child classes are guaranteed to have the parent's interface.
- Extensibility — you can add specialist behaviour in the child without touching the parent.
How do you write a parent class?
Start by writing a general Animal class with attributes and methods that every animal shares:
class Animal:
def __init__(self, name, age):
self.name = name
self.age = age
def breathe(self):
print(f"{self.name} breathes.")
def describe(self):
print(f"{self.name} is {self.age} years old.")
How do you create a child class that inherits from it?
Pass the parent class name inside brackets after the child class name:
class Dog(Animal): # Dog inherits from Animal
def __init__(self, name, age, breed):
super().__init__(name, age) # call parent's __init__
self.breed = breed # add Dog-specific attribute
def speak(self): # add Dog-specific method
print(f"{self.name} says: Woof!")
super().__init__(name, age) calls the parent's constructor, so you do not have to repeat the self.name = name and self.age = age assignments.
What does a child class inherit and what can it add?
fido = Dog("Fido", 3, "Labrador")
fido.breathe() # Inherited from Animal → "Fido breathes."
fido.describe() # Inherited from Animal → "Fido is 3 years old."
fido.speak() # Defined in Dog → "Fido says: Woof!"
print(fido.breed) # Dog-specific attr → "Labrador"
The child class has everything the parent has, plus anything the child defines itself.
What is method overriding?
Method overriding occurs when a child class defines a method with the same name as one in the parent, replacing the parent's version for that child:
class Cat(Animal):
def __init__(self, name, age, indoor):
super().__init__(name, age)
self.indoor = indoor
def describe(self): # overrides Animal.describe()
print(f"{self.name} is {self.age} years old and is "
f"{'an indoor' if self.indoor else 'an outdoor'} cat.")
whiskers = Cat("Whiskers", 5, True)
whiskers.describe()
# Whiskers is 5 years old and is an indoor cat.
The Cat version of describe() runs instead of the Animal version. The parent's version is still accessible via super().describe() if needed.
What does an inheritance hierarchy look like?
Inheritance can extend over multiple levels — a grandparent, parent, and child structure:
Animal
/ \
Dog Cat
/ \
Guide Sniffer
Dog Dog
Each level adds more specialist behaviour. A GuideDog inherits everything from Dog (which inherited everything from Animal) and then adds guide-specific abilities.
| Class level | What it adds |
|---|---|
Animal |
name, age, breathe(), describe() |
Dog |
breed, speak() |
GuideDog |
handler_name, guide() |
How does inheritance relate to the four pillars of OOP?
Inheritance is one of the four fundamental OOP principles:
- Encapsulation — data and methods bundled inside a class.
- Inheritance — child classes reuse and extend parent classes. ← this article.
- Polymorphism — different child classes respond to the same method name differently (e.g.
speak()returns "Woof" for a dog and "Meow" for a cat). - Abstraction — complex implementation details are hidden behind simple method names.
Frequently asked questions
What is the difference between a parent class and a child class?
The parent class (also called superclass or base class) is the more general template. The child class (also called subclass or derived class) inherits from the parent, gains all its attributes and methods, and can add or override them.
Do I always have to use super().init()?
You should call super().__init__() whenever the child class has its own __init__ method and needs to initialise the parent's attributes as well. If you omit it, the parent's __init__ does not run, so self.name and self.age would not be set, and any parent method that uses them would fail.
Can a class inherit from more than one parent in Python?
Yes — Python supports multiple inheritance, where a class lists several parent classes: class C(A, B):. This is an advanced topic beyond typical GCSE scope, but it is worth knowing it exists.
Is inheritance always the right design choice?
Not always. A useful rule of thumb is the "is-a" test: use inheritance if the child is a type of the parent (a dog is an animal). If the relationship is more like "has a" (a car has an engine), prefer composition — store the engine as an attribute rather than inheriting from it.
Want to practise writing parent and child classes with instant GCSE-style feedback? Visit aitutors.me and let Professor Turing guide you through an OOP design challenge.