ComparisonComparisons

@staticmethod vs @classmethod

@staticmethod behaves like a plain function with no automatic argument, while @classmethod receives the class as cls and usually serves as an alternative constructor.

On this page

Side-by-side comparison

#

Example

#
Python
class Grade:
    def __init__(self, points):
        self.points = points

    @staticmethod
    def is_valid(points):
        return 0 <= points <= 100

    @classmethod
    def from_percent(cls, percent, maximum):
        return cls(round(percent / 100 * maximum))

print(Grade.is_valid(120))
grade = Grade.from_percent(75, 80)
print(grade.points)
Resultsaved result, you can check it
False
60

Definition and usage

#

Both decorators define a method you can call through the class name, without creating an object. Neither one receives self, so neither has access to a specific object’s data.

They differ in their first argument. A static method gets nothing automatically: it’s a plain function, just placed inside the class for organization. A class method gets the class itself (cls) as its first argument, which lets it reference the class’s attributes and, more importantly, create an object through cls(...). In a derived class, cls points to that derived class, not to the class where the method was written.

Use @staticmethod for a helper function that logically belongs to the class, e.g. validation or a calculation, but needs neither an object nor the class. Use @classmethod when the method should create objects from data in a different format than the regular constructor, e.g. from_text() or from_dict(), or when it needs access to class attributes, such as a shared counter.

Syntax

#
Syntax
class Name:
    @staticmethod
    def method(arg):
        ...

    @classmethod
    def other(cls, arg):
        return cls(arg)

More examples

#
cls in a derived class creates the right type
Python
class Task:
    def __init__(self, number):
        self.number = number

    @classmethod
    def from_code(cls, code):
        return cls(code.removeprefix("task_"))

class Quiz(Task):
    pass

task = Quiz.from_code("task_7_3")
print(type(task).__name__, task.number)
Resultsaved result, you can check it
Quiz 7_3
A static method sees neither the class nor the object
Python
class Course:
    count = 0

    def __init__(self, title):
        self.title = title
        Course.count += 1

    @staticmethod
    def slugify(title):
        return title.lower().replace(" ", "-")

python_course = Course("Python from scratch")
print(Course.slugify(python_course.title))
print(Course.count)
Resultsaved result, you can check it
python-from-scratch
1

Good practices

#
  • If a method uses neither self nor cls, it probably should be static, or not in the class at all.
  • Name alternative constructors with a from_ prefix, e.g. from_json(), from_row(). It’s a convention familiar from the standard library.
  • In a class method, create objects through cls(...), not a hardcoded class name, so it also works correctly in derived classes.

Related entries

#

Spotted a mistake or missing an example? Write to us.