Inheritance

Building one class on top of another: the derived class inherits the base class’s methods and can extend or override them.

On this page

Example

#
Python
class User:
    def __init__(self, name):
        self.name = name

    def greet(self):
        return f"Hi, I'm {self.name}"

    def role(self):
        return "user"

class Mentor(User):
    def role(self):
        return "mentor"

    def review(self, task):
        return f"{self.name} is reviewing task {task}"

darwin = Mentor("Darwin")
print(darwin.greet())
print(darwin.role())
print(darwin.review("7_3"))
print(isinstance(darwin, User), issubclass(Mentor, User))
Resultsaved result, you can check it
Hi, I'm Darwin
mentor
Darwin is reviewing task 7_3
True True

Definition and usage

#

Inheritance lets you create a new class based on an existing one. You give the base class in parentheses after the name: class Mentor(User). The derived class automatically gets all the methods and attributes of the base class, so you only write what is new or different in it.

A method with the same name in the derived class overrides the base version. Python looks for a method first in the object’s own class, then in its base class, and so on, up to the built-in object class that every class inherits from. The attribute __mro__ shows this order (MRO, for method resolution order). From an overridden method, you call the base version through super().

The function isinstance(object, Class) returns True for objects of derived classes too, while issubclass(A, B) checks the relationship between the classes themselves. This means code written for the base class works with every derived class, and each one can respond to the same call in its own way. This is called polymorphism.

A class can inherit from several classes at once (class Quiz(Timed, Scored)), which is useful for small classes that each add one capability, so-called mixins. Use inheritance when an "is-a" relationship holds: a mentor is a user. When an object merely "has" another object, for example a course has a list of lessons, store it as an attribute instead. This approach is called composition.

Syntax

#
Syntax
class Base:
    ...

class Derived(Base):
    ...

class Derived(Base1, Base2):
    ...

More examples

#
Polymorphism: one loop, different classes
Python
class Task:
    def __init__(self, exp):
        self.exp = exp

    def reward(self):
        return self.exp

class BonusTask(Task):
    def reward(self):
        return self.exp * 2

class Tutorial(Task):
    def reward(self):
        return 0

tasks = [Task(10), BonusTask(10), Tutorial(10)]
print([task.reward() for task in tasks])
print(sum(task.reward() for task in tasks))
Resultsaved result, you can check it
[10, 20, 0]
30
The method search order (MRO)
Python
class Exercise:
    def describe(self):
        return "task"

class Timed(Exercise):
    def describe(self):
        return "a timed task"

class Scored(Exercise):
    def describe(self):
        return "a scored task"

class Quiz(Timed, Scored):
    pass

print(Quiz().describe())
print([cls.__name__ for cls in Quiz.__mro__])
Resultsaved result, you can check it
a timed task
['Quiz', 'Timed', 'Scored', 'Exercise', 'object']
A family of custom exceptions
Python
class CodeWorldsError(Exception):
    pass

class NoFuelError(CodeWorldsError):
    pass

class LockedWorldError(CodeWorldsError):
    pass

for error in [NoFuelError("Out of fuel"), LockedWorldError("World 9 is locked")]:
    try:
        raise error
    except CodeWorldsError as caught:
        print(type(caught).__name__, "->", caught)
Resultsaved result, you can check it
NoFuelError -> Out of fuel
LockedWorldError -> World 9 is locked

Good practices

#
  • Only inherit when an object of the derived class truly "is" an object of the base class. If it merely uses it, store it as an attribute instead.
  • Avoid deep hierarchies. Two or three levels are usually enough, and each additional one makes it harder to tell where a given method comes from.
  • Derive your custom exceptions from a shared base class. A single except on the base class then handles the whole family of errors.

Related entries

#

Spotted a mistake or missing an example? Write to us.