Python
base class
classmethod
inheritance
programming

Calling a base class's classmethod in Python

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Calling a base class's classmethod in Python is straightforward, but the result depends on how you call it. Base.method() and super().method() are not interchangeable, because they pass different class objects as cls. This article explains the difference and shows which form to use depending on whether you want base-class behavior or inherited polymorphic behavior.

How classmethod Binding Works

A classmethod receives the class as its first argument, conventionally named cls.

python
1class Base:
2    @classmethod
3    def describe(cls):
4        print(f"called on {cls.__name__}")
5
6
7Base.describe()  # called on Base

If a subclass calls an inherited classmethod directly, cls becomes the subclass:

python
1class Child(Base):
2    pass
3
4
5Child.describe()  # called on Child

That is the normal polymorphic behavior of classmethods.

Call the Base Class Method Explicitly

If you want to invoke the base implementation directly, use the base class name.

python
1class Base:
2    @classmethod
3    def describe(cls):
4        print(f"Base implementation, cls={cls.__name__}")
5
6
7class Child(Base):
8    @classmethod
9    def show_base(cls):
10        Base.describe()
11
12
13Child.show_base()

In this form, the method is bound to Base, so cls inside describe is Base, not Child.

Use super() When You Want Cooperative Inheritance

Inside an overridden classmethod, super() calls the next implementation in the method resolution order while still preserving the subclass as cls.

python
1class Base:
2    @classmethod
3    def describe(cls):
4        print(f"Base sees {cls.__name__}")
5
6
7class Child(Base):
8    @classmethod
9    def describe(cls):
10        print("Child before")
11        super().describe()
12        print("Child after")
13
14
15Child.describe()

Output:

text
Child before
Base sees Child
Child after

This is the key distinction. super().describe() uses the base implementation, but it still passes Child as cls.

When to Use Each Form

Use Base.method() when:

  • you specifically want the method bound to Base
  • the base implementation should behave as if called on Base
  • you do not want subclass-specific class state to flow through

Use super().method() when:

  • you are extending an inherited classmethod
  • cooperative inheritance matters
  • the base implementation should still operate on the current subclass

This difference matters a lot for factories and alternate constructors.

Example with an Alternate Constructor

Consider a base classmethod that builds an instance using cls.

python
1class Base:
2    def __init__(self, name):
3        self.name = name
4
5    @classmethod
6    def from_name(cls, name):
7        return cls(name)
8
9
10class Child(Base):
11    pass
12
13
14obj = Child.from_name("alice")
15print(type(obj).__name__)  # Child

If you call Base.from_name("alice"), you get a Base. If you call it through super() inside Child, cls is still Child, so the factory remains subclass-aware.

Explicit Base Call vs super() in Factories

This example shows the difference clearly:

python
1class Base:
2    @classmethod
3    def build(cls):
4        return cls()
5
6
7class Child(Base):
8    @classmethod
9    def build_via_super(cls):
10        return super().build()
11
12    @classmethod
13    def build_via_base(cls):
14        return Base.build()
15
16
17print(type(Child.build_via_super()).__name__)  # Child
18print(type(Child.build_via_base()).__name__)   # Base

If your intent is subclass-preserving construction, super() is usually the right tool.

Multiple Inheritance Considerations

In multiple inheritance, super() is even more valuable because it respects Python's method resolution order. Hard-coding Base.method() skips that cooperative chain and can break mixin-based designs.

That is why super() is generally the preferred extension mechanism unless you truly need to bypass polymorphism.

Common Pitfalls

  • Assuming Base.method() and super().method() pass the same cls.
  • Hard-coding a base class call inside frameworks that rely on cooperative inheritance.
  • Using Base.method() in an alternate constructor when you actually wanted a subclass instance.
  • Forgetting that inherited classmethods are already polymorphic when called on the subclass.
  • Overusing explicit base calls when super() would better preserve method resolution order.

Summary

  • A Python classmethod receives the bound class as cls.
  • 'Base.method() binds the call to Base.'
  • 'super().method() uses the base implementation but still passes the current subclass as cls.'
  • For extension and cooperative inheritance, prefer super().
  • For explicitly base-bound behavior, call the base class by name.

Course illustration
Course illustration

All Rights Reserved.