Python super() Function Examples

The Python super() function returns a helper object that lets a class call methods from the next class in the method resolution order. In everyday code, that usually means calling a parent class method from a child class.

The official Python documentation covers super(), and the data model documentation explains method resolution order. Related PythonPool guides include class vs module, cls vs self, multiple constructors, importing classes, and getattr().

Use super() when a subclass should extend existing behavior instead of replacing it completely. The most common use is calling super().__init__() so the parent class can initialize its own attributes before the child adds more.

In Python 3, you normally call super() without arguments inside an instance method. Older examples sometimes use super(ClassName, self), but the zero-argument form is shorter and less error-prone when classes are renamed.

The goal is not just to avoid typing a parent class name. super() follows Python’s MRO, so it can work correctly in class hierarchies where more than one parent participates. That makes it safer than hard-coding a parent call in reusable base classes.

Use inheritance only when the relationship is clear. If a class only needs a helper function from another class, composition may be simpler than building a parent-child hierarchy.

Call A Parent Method

A child class can use super() to reuse a method from its parent.

class Animal:
    def speak(self):
        return "sound"


class Dog(Animal):
    def speak(self):
        return super().speak() + " bark"


dog = Dog()
print(dog.speak())

The child method adds text to the parent result. This is extension, not a full replacement.

Use this when the parent method already does part of the job and the subclass only needs to add or adjust behavior.

Keep the parent result in a local name when the extension becomes more than one expression. That makes debugging easier and avoids hiding too much work in a single return line.

Use super In __init__

The most common pattern is calling super().__init__() from a subclass initializer.

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


class Admin(User):
    def __init__(self, name, level):
        super().__init__(name)
        self.level = level


admin = Admin("Ada", 5)
print(admin.name)
print(admin.level)

The parent stores name, and the child stores level. Without the super() call, name would not be initialized by the parent class.

This keeps each class responsible for its own attributes and avoids copying parent initialization code into every subclass.

Constructor chaining also protects future changes. If the parent later validates the name or adds another attribute, subclasses that call super().__init__() automatically keep that setup.

Override And Extend Behavior

A subclass can call the parent method, then add validation, formatting, logging, or extra data.

class Report:
    def title(self):
        return "Monthly report"


class DraftReport(Report):
    def title(self):
        return "[DRAFT] " + super().title()


report = DraftReport()
print(report.title())

This pattern is useful when the subclass should preserve the parent rule while making the output more specific.

If the subclass should completely replace the behavior, skip super() and write the new method directly.

A good override should make its intent obvious. Either it extends the parent with super(), or it deliberately replaces the behavior. Mixing both styles without a clear reason makes class behavior harder to predict.

Inspect Method Resolution Order

super() follows the class method resolution order, often shortened to MRO.

class A:
    pass


class B(A):
    pass


class C(B):
    pass


print([cls.__name__ for cls in C.mro()])

The output shows the order Python uses when searching for methods. In this simple chain, Python checks C, then B, then A, then object.

Understanding MRO becomes more important when a class inherits from multiple parents.

When a method call produces surprising output, printing the MRO is often the fastest way to see which class Python will check next.

Cooperative Multiple Inheritance

In multiple inheritance, every class that participates should call super() with compatible arguments.

class Base:
    def describe(self):
        return ["Base"]


class Left(Base):
    def describe(self):
        return ["Left"] + super().describe()


class Right(Base):
    def describe(self):
        return ["Right"] + super().describe()


class Child(Left, Right):
    def describe(self):
        return ["Child"] + super().describe()


print(Child().describe())

The result follows the MRO and calls each class once. This is the reason super() is preferred over directly naming the parent class in cooperative designs.

For this to work well, methods in the chain need compatible signatures and each method needs to pass control onward.

In larger frameworks, this style is common for setup hooks, mixins, and extension points. Every class does its part, then lets the next class in the MRO continue the chain.

Avoid Hard-Coding Parent Calls

Direct parent calls can work in simple inheritance, but they bypass MRO cooperation.

class Parent:
    def label(self):
        return "parent"


class Child(Parent):
    def label(self):
        return super().label().upper()


print(Child().label())

This version lets Python choose the next method in the resolution order. If the class hierarchy changes later, the call is less likely to point at the wrong parent.

Direct parent calls are still sometimes used in very small hierarchies, but they should be a conscious choice. If multiple inheritance or mixins may appear later, super() is the more flexible habit.

The practical rule is simple: use super() when extending inherited behavior, especially inside __init__(). Keep method signatures compatible in inheritance chains, inspect ClassName.mro() when behavior is surprising, and avoid hard-coded parent calls in cooperative multiple inheritance.

Good tests should confirm that parent attributes are initialized, overridden methods still include parent behavior when expected, and multiple-inheritance chains call each participant only once.

Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted