Unit 6 • Lesson 9

The super() Function

Overview

super() gives you access to a parent class's methods from a child class. You'll use it to extend base functionality and avoid code duplication when working with inherited classes, creating more maintainable inheritance hierarchies.

Intermediate 20–25 min

What You Will Learn in This Lesson

By the end of this lesson, you will know:

  • What super() is: Understand what the super() function does and why it's useful.
  • Calling parent methods: Learn how to call parent class methods from a child class.
  • Extending functionality: See how super() helps you extend parent methods instead of replacing them.
  • Multiple inheritance: Understand how super() works with multiple parent classes.
  • Real-world examples: Practice using super() in practical scenarios.

Understanding super()

When you override a method in a subclass, you completely replace the parent's version. But sometimes, you want to extend the parent method — keep what it does, but add more functionality. That's where super() comes in.

What is super()?

super() is a built-in Python function that gives you access to methods and attributes from a parent class. It's like saying "do what my parent does, then do my own thing too."

Example: Without super()

Imagine you have a parent class that initializes some attributes, and a child class that needs to add more:

class Animal:
    def __init__(self, name):
        self.name = name
        print(f"Animal {self.name} created")

class Dog(Animal):
    def __init__(self, name, breed):
        self.name = name  # Duplicating parent code!
        print(f"Animal {self.name} created")  # Duplicating parent code!
        self.breed = breed
        print(f"Dog {self.name} is a {self.breed}")

dog = Dog("Buddy", "Golden Retriever")

This works, but we're duplicating code from the parent class. If the parent class changes, we'd have to update the child class too.

Example: With super()

Now let's use super() to call the parent's __init__ method:

class Animal:
    def __init__(self, name):
        self.name = name
        print(f"Animal {self.name} created")

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)  # Call parent's __init__
        self.breed = breed
        print(f"Dog {self.name} is a {self.breed}")

dog = Dog("Buddy", "Golden Retriever")

Much cleaner! The parent class handles its own initialization, and the child class adds its own attributes.

How super() Works

super() returns a temporary object that represents the parent class. When you call a method on it, Python looks up the method in the parent class and executes it.

Syntax

super().method_name(arguments)

Inside a method, super() automatically knows which parent class to use based on the current class.

Try It Yourself

Run this code to see how super() calls the parent method:

Press Run to see output

What happened?

When you call car.start(), Python first calls the parent's start() method (via super().start()), which prints "Vehicle engine started". Then it continues with the child's code, printing "Car is ready to drive". This is called extending the parent method.

Extending Parent Methods

The most common use of super() is in the __init__ method. When a child class needs to initialize its own attributes, it should first call the parent's __init__ to set up inherited attributes.

Example: Extending __init__

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def introduce(self):
        return f"Hi, I'm {self.name}, {self.age} years old"

class Student(Person):
    def __init__(self, name, age, student_id):
        super().__init__(name, age)  # Initialize parent attributes
        self.student_id = student_id  # Add child-specific attribute
    
    def introduce(self):
        parent_intro = super().introduce()  # Get parent's introduction
        return f"{parent_intro}. My student ID is {self.student_id}"

student = Student("Alice", 20, "S12345")
print(student.introduce())

Try It Yourself

Create a Teacher class that extends Person and adds a subject attribute:

Press Run to see output

super() with Regular Methods

You can use super() with any method, not just __init__. This is useful when you want to add functionality to a parent method without completely replacing it.

Example: Extending a Regular Method

class Shape:
    def area(self):
        return 0
    
    def describe(self):
        return f"This shape has an area of {self.area()}"

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def area(self):
        return self.width * self.height
    
    def describe(self):
        parent_desc = super().describe()  # Get parent's description
        return f"{parent_desc}. It's a rectangle with width {self.width} and height {self.height}"

rect = Rectangle(5, 3)
print(rect.describe())

Key Point

Notice that super().describe() calls the parent's describe() method, which in turn calls self.area(). But since self is a Rectangle object, Python uses the overridden area() method from the Rectangle class, not the parent's version. This is polymorphism in action!

super() in Multiple Inheritance

When a class inherits from multiple parents, super() follows Python's Method Resolution Order (MRO) to determine which parent to call. This ensures methods are called in a consistent order.

Example: Multiple Inheritance

class A:
    def method(self):
        print("A's method")

class B:
    def method(self):
        print("B's method")

class C(A, B):
    def method(self):
        super().method()  # Calls A's method (first in MRO)
        print("C's method")

c = C()
c.method()

Python determines the order based on how classes are listed in the inheritance: class C(A, B) means A comes before B in the MRO.

Note

Multiple inheritance can be complex. For now, focus on single inheritance (one parent class). When you're comfortable with that, you can explore multiple inheritance more deeply.

Common Patterns with super()

Here are some common ways you'll use super() in real code:

Pattern 1: Initialization Chain

class Base:
    def __init__(self):
        print("Base initialized")

class Middle(Base):
    def __init__(self):
        super().__init__()
        print("Middle initialized")

class Top(Middle):
    def __init__(self):
        super().__init__()
        print("Top initialized")

obj = Top()

This creates a chain: Top → Middle → Base. Each class initializes itself and then calls the parent.

Pattern 2: Adding Validation

class BankAccount:
    def __init__(self, balance):
        self.balance = balance
    
    def withdraw(self, amount):
        self.balance -= amount
        return self.balance

class SavingsAccount(BankAccount):
    def withdraw(self, amount):
        if amount > self.balance:
            raise ValueError("Insufficient funds")
        return super().withdraw(amount)  # Call parent after validation

account = SavingsAccount(100)
print(account.withdraw(50))
print(account.withdraw(60))  # This will raise an error

The child class adds validation, then calls the parent method to do the actual work.

End-of-Lesson Exercises

Complete these exercises to practice using super():

Exercise 1: Extend Animal Class

Create a Cat class that extends Animal. The Cat should call the parent's __init__ using super() and add a color attribute. Then override the make_sound() method to print "Meow" but also call the parent's make_sound() first.

Write your code above and click "Check Answer" to verify it's correct.

Exercise 2: Extend Employee Class

Create a Manager class that extends Employee. Use super() to call the parent's __init__ and add a team_size attribute. Override the get_info() method to include the team size in the output, but first get the parent's info using super().

Write your code above and click "Check Answer" to verify it's correct.