DMarlon Studio

Lesson 9 · 9 of 20

Inheritance and super() · Python

Reuse and specialise Python classes with inheritance: subclasses, super(), method overriding, isinstance and the MRO, using a payroll.

Python · Inheritance and super() in DMarlon Studio: the example's code and its output in the terminal

class Manager(Employee) creates a subclass: a Manager is an Employee and inherits everything it has (name, salary, describe()…) without rewriting it.

Manager's __init__ needs one more piece of data, bonus. Instead of copying the parent's code, it calls `super().__init__(name, salary)` so Employee sets up its part, and then adds its own. Intern has no __init__, so it uses the parent's as it is.

Both subclasses override monthly_pay(): a method with the same name replaces the inherited one. Manager reuses the parent's calculation with super().monthly_pay() and adds the bonus; Intern returns a fixed grant.

The powerful part is polymorphism: describe() is written once in Employee, yet self.monthly_pay() calls the method of the object's actual class each time, and type(self).__name__ prints that class. The loop treats everyone the same and each object answers in its own way.

isinstance(staff[1], Employee) is True because a manager is also an employee, and issubclass compares classes. Manager.__mro__ is the method resolution order: the list of classes Python searches for each method, from the most specific down to object.

Code · main.py

class Employee:    def __init__(self, name, salary):        self.name = name        self.salary = salary    def monthly_pay(self):        return self.salary / 12    def describe(self):        return f"{self.name:<6} {type(self).__name__:<9} {self.monthly_pay():>8.2f}"class Manager(Employee):              # Manager is an Employee    def __init__(self, name, salary, bonus):        super().__init__(name, salary)    # let the parent set its part        self.bonus = bonus    def monthly_pay(self):            # override: same name, new behaviour        return super().monthly_pay() + self.bonus / 12class Intern(Employee):    def monthly_pay(self):        return 800.0                  # fixed grantstaff = [Employee("Lucia", 30000), Manager("Pablo", 48000, 6000),         Intern("Iker", 0)]for person in staff:                  # the same call, the right method    print(person.describe())print("Payroll:", round(sum(p.monthly_pay() for p in staff), 2))print("Pablo is an Employee:", isinstance(staff[1], Employee))print("Manager subclass of Employee:", issubclass(Manager, Employee))print("Method order:", [c.__name__ for c in Manager.__mro__])

Output · python3 main.py

Lucia  Employee   2500.00
Pablo  Manager    4500.00
Iker   Intern      800.00
Payroll: 7800.0
Pablo is an Employee: True
Manager subclass of Employee: True
Method order: ['Manager', 'Employee', 'object']

Key points

  • class Child(Parent) inherits attributes and methods.
  • super() calls the parent's version.
  • A method with the same name overrides the inherited one.
  • isinstance accepts subclasses too.
  • The MRO is the order in which methods are looked up.

Exercise

Create a Contractor subclass paid by the hour (hours * rate) and add a contractor to staff so they show up in the payroll.