Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

The @classmethod decorator is a built-in Python class (type) that alters the binding of a method, attaching it to the class itself rather than to a specific instance. When applied, it modifies the method signature to accept the class object as its first implicit argument (conventionally named cls), bypassing the standard instance reference (self).
class ExampleClass:
    @classmethod
    def method_name(cls, *args, **kwargs):
        # 'cls' holds the reference to ExampleClass
        return cls

Technical Mechanics

Method Binding and the Descriptor Protocol Under the hood, @classmethod implements the descriptor protocol. When a decorated method is accessed, the __get__ method of the @classmethod descriptor is invoked. This returns a bound method object where the __self__ attribute is explicitly set to the class type. Consequently, whether the method is called via the class or an instance, the Python interpreter automatically injects the class object as the first positional argument. Invocation A class method can be invoked in two ways. In both scenarios, the underlying class is passed to cls:
  1. Via the class: ExampleClass.method_name()
  2. Via an instance: instance_obj.method_name() (Python resolves the instance’s type and passes it to cls).
Inheritance and Polymorphism The cls parameter is dynamically evaluated based on the class that invokes the method, not the class where the method was originally defined. If a subclass inherits a class method and calls it, the subclass type is passed to cls.
class Base:
    @classmethod
    def get_class_reference(cls):
        return cls

class Derived(Base):
    pass


# The 'cls' argument dynamically binds to the calling class
print(Base.get_class_reference())    # Output: <class '__main__.Base'>
print(Derived.get_class_reference()) # Output: <class '__main__.Derived'>


# Calling via an instance resolves to the instance's class
obj = Derived()
print(obj.get_class_reference())     # Output: <class '__main__.Derived'>

Primary Use Case: Alternative Constructors

Because Python classes only support a single __init__ method, the primary practical application for @classmethod is creating alternative constructors (factory methods). This allows developers to instantiate objects from varying input formats or data structures. By calling cls(...) within the method, it dynamically creates and returns a new instance of the class, respecting inheritance.
class User:
    def __init__(self, username, email):
        self.username = username
        self.email = email

    @classmethod
    def from_string(cls, data_string):
        # Parses a string like "johndoe-john@example.com"
        username, email = data_string.split('-')
        # cls() acts as User(), but will correctly resolve to a subclass if inherited
        return cls(username, email)

    @classmethod
    def from_dict(cls, data_dict):
        return cls(data_dict['username'], data_dict['email'])


# Usage of alternative constructors
user1 = User.from_string("admin-admin@system.local")
user2 = User.from_dict({"username": "guest", "email": "guest@system.local"})

Signature Comparison

To understand @classmethod mechanically, it is best contrasted with standard and static methods regarding argument injection:
  • Instance Method: def method(self):
    • Bound to: The instance.
    • Implicit first argument: The instance object (self).
  • Class Method: @classmethod def method(cls):
    • Bound to: The class.
    • Implicit first argument: The class object (cls).
  • Static Method: @staticmethod def method():
    • Bound to: Neither.
    • Implicit first argument: None (behaves like a standard module-level function housed within a class namespace).
Master Python with Deep Grasping Methodology!Learn More