classmethod vs staticmethod

Difficulty: Intermediate

Question

What is the difference between @classmethod and @staticmethod in Python?

Answer

@classmethod: receives the class as the first argument (cls instead of self). Can access and modify class state. Used for alternative constructors and factory methods.

@staticmethod: receives no implicit first argument. Cannot access class or instance state. Used for utility functions logically grouped with the class but not needing class/instance access.

Regular method: receives the instance (self). Can access both instance and class state.

When to use: - classmethod: alternative constructors, factory methods, class-level state - staticmethod: helper functions that do not need class or instance

Code examples

classmethod as Alternative Constructor

from datetime import date

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def from_birth_year(cls, name, birth_year):
        """Alternative constructor."""
        age = date.today().year - birth_year
        return cls(name, age)  # cls is Person (or subclass!)

    @classmethod
    def from_dict(cls, data):
        return cls(data['name'], data['age'])

    @staticmethod
    def validate_age(age):
        """Utility - no need for cls or self."""
        return 0 <= age <= 150

    def __repr__(self):
        return f'Person(name={self.name!r}, age={self.age})'

p1 = Person('Alice', 30)
p2 = Person.from_birth_year('Bob', 1995)
p3 = Person.from_dict({'name': 'Charlie', 'age': 25})

print(p1, p2, p3)
print(Person.validate_age(200))  # False

# classmethod with inheritance
class Employee(Person):
    pass

e = Employee.from_birth_year('Dave', 1990)
print(type(e))  # <class 'Employee'> - cls is Employee!

cls is the class itself (or subclass). When called on Employee, cls is Employee - classmethod constructors preserve polymorphism.

When to Use Each

class MathHelper:
    # Regular method: needs instance
    def double(self, x):
        return x * 2

    # classmethod: creates instance, modifies class state
    @classmethod
    def create_with_multiplier(cls, multiplier):
        obj = cls()
        obj._multiplier = multiplier
        return obj

    # staticmethod: pure utility, no cls/self needed
    @staticmethod
    def is_even(n):
        return n % 2 == 0

    @staticmethod
    def gcd(a, b):
        while b:
            a, b = b, a % b
        return a

print(MathHelper.is_even(4))    # True
print(MathHelper.gcd(48, 18))   # 6

# Calling on instance is also valid
m = MathHelper()
print(m.is_even(7))    # False (still works)
print(m.gcd(100, 75))  # 25

# Comparison summary
class Demo:
    class_var = 'shared'

    def instance_method(self):
        return self  # Has access to instance

    @classmethod
    def class_method(cls):
        return cls  # Has access to class

    @staticmethod
    def static_method():
        return 'no access to cls or self'

staticmethod is a plain function with namespace. classmethod gets the class. Regular method gets the instance. All three can be called on instances.

Key points

Concepts covered

classmethod, staticmethod, cls, Factory Methods, Alternative Constructors