← Python lessons

Python Inheritance: Subclasses and Parent Classes

Inheritance builds a new class on top of an existing one. The subclass gets every method and attribute of its parent class, and can add its own.

Read Methods and self first.

Create a subclass

Put the parent class in brackets after the new class name.

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

    def describe(self):
        return f"{self.name} is an animal"

class Dog(Animal):
    def fetch(self):
        return f"{self.name} fetches the ball"

rex = Dog("Rex")
print(rex.describe())
print(rex.fetch())

Dog has no __init__ or describe of its own. It uses the ones from Animal, and adds fetch.

Check a type with isinstance()

An instance of a subclass also counts as an instance of its parent. The reverse is not true.

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

class Dog(Animal):
    pass

rex = Dog("Rex")
tom = Animal("Tom")
print(isinstance(rex, Dog))
print(isinstance(rex, Animal))
print(isinstance(tom, Dog))
print(issubclass(Dog, Animal))

isinstance(object, class) asks "is this object that kind of thing?". issubclass(child, parent) asks the same about two classes.

Share code between subclasses

Put the code every subclass needs in the parent, once. Each subclass adds only what makes it different.

class Vehicle:
    def __init__(self, name, wheels):
        self.name = name
        self.wheels = wheels

    def summary(self):
        return f"{self.name}: {self.wheels} wheels"

class Bike(Vehicle):
    def ring(self):
        return "Ring ring!"

class Truck(Vehicle):
    def load(self, tonnes):
        return f"Carrying {tonnes} tonnes"

for vehicle in [Bike("Bike", 2), Truck("Truck", 6)]:
    print(vehicle.summary())
print(Bike("Bike", 2).ring())

The loop calls summary on both, because both inherit it from Vehicle. Only a Bike has ring.

How Python finds a method

Python looks for a method in the object's own class first. Then it tries the parent, then the parent's parent. Every class ends at object.

class Animal:
    def describe(self):
        return "an animal"

class Dog(Animal):
    pass

class Puppy(Dog):
    pass

print(Puppy().describe())
print([cls.__name__ for cls in Puppy.__mro__])

__mro__ is that search order (the method resolution order). Puppy and Dog have no describe, so Python uses the one in Animal.

Note: Use inheritance when the subclass really is a kind of the parent: a Dog is an Animal. When one object only has another, such as a Car that has an Engine, store it as an attribute instead.

See also: Method overriding and super(), Classes and objects.

Your turn

Add a SavingsAccount class that inherits from Account. Give it an add_interest() method that adds self.balance // 10 to the balance.

class Account:
    def __init__(self, owner):
        self.owner = owner
        self.balance = 0

    def deposit(self, amount):
        self.balance += amount

# add three lines: class SavingsAccount(Account) with an add_interest method

savings = SavingsAccount("Mia")
savings.deposit(50)
savings.add_interest()
print(savings.owner, savings.balance)
print(isinstance(savings, Account))

Expected output

Mia 55
True

Practise this in the free Python course, where every exercise checks your code instantly.