Question

Python @classmethod vs @staticmethod Explained for Beginners

pythonoopstatic-methodsclass-method

Question

What do @classmethod and @staticmethod mean in Python, and how are they different? When should they be used, why are they useful, and how do you write them correctly?

I understand that @classmethod somehow relates a method to the class rather than an object instance, but I am not clear on what that really means in practice. I also want to understand why these decorators are needed at all. Why not just define methods normally without using @classmethod, @staticmethod, or any other @ decorators?

Short Answer

By the end of this page, you will understand the difference between instance methods, class methods, and static methods in Python. You will learn what self and cls mean, why @classmethod and @staticmethod exist, when to use each one, and how these choices affect inheritance, object creation, and code organization.

Concept

In Python, methods inside a class are not all the same. The main difference is what gets passed automatically as the first argument.

There are three common method types:

  1. Instance methods

    • Defined normally.
    • Receive the current object as the first argument, usually named self.
    • Used when the method needs to read or change data stored in a specific object.
  2. Class methods

    • Marked with @classmethod.
    • Receive the class itself as the first argument, usually named cls.
    • Used when the method needs to work with class-level data or create objects in an alternative way.
  3. Static methods

    • Marked with @staticmethod.
    • Do not receive self or cls automatically.
    • Used when the function logically belongs inside the class, but does not need instance data or class data.

Why decorators are needed

Python needs a way to know how a method should behave when it is called.

  • A normal method becomes an instance method.
  • @classmethod tells Python: "Pass the class as the first argument."
  • @staticmethod tells Python: "Do not pass anything automatically."

Without these decorators, Python would treat the method as a normal instance method.

Why this matters

Choosing the right method type makes your code:

  • easier to understand
  • easier to maintain
  • better for inheritance
  • more explicit about what data a method depends on

For example:

  • If a method needs self.name, it should be an instance method.
  • If a method needs cls.default_timeout, it should be a class method.
  • If a method just validates a string and does not need object or class state, it can be a static method.

Mental Model

Think of a class like a blueprint for making objects.

  • An instance method is like talking to one specific product made from the blueprint.
    • Example: "What is this user's email?"
  • A class method is like talking to the blueprint itself.
    • Example: "Make a new user from this CSV row."
  • A static method is like a tool stored in the blueprint's toolbox.
    • It belongs near the class because it is related, but it does not need the blueprint or any specific product.

Another way to remember it:

  • self = this object
  • cls = this class
  • @staticmethod = no automatic object or class argument
Take Quiz

Syntax and Examples

Core syntax

class Example:
    class_value = 10

    def instance_method(self):
        return f"Instance method: {self}"

    @classmethod
    def class_method(cls):
        return f"Class method: {cls.class_value}"

    @staticmethod
    def static_method(x, y):
        return x + y

Example with all three

class User:
    default_role = "member"

    def __init__(self, name, role=None):
        self.name = name
        self.role = role or User.default_role

    def describe(self):
        return f"{self.name} is a {self.role}"

    @classmethod
    def guest(cls, name):
        return cls(name, role="guest")

    @staticmethod
    def is_valid_name(name):
        return isinstance(name, str) and len(name.strip()) > 0

How to use it

user = User("Ava")

print(user.describe())
print(User.guest("Sam").describe())
print(User.is_valid_name("Mia"))

What each part does

  • describe(self) uses data from a specific User object.
  • guest(cls, name) creates a new User in an alternative way.
  • is_valid_name(name) is a helper function related to User, but it does not need self or cls.

Why cls(...) is important

Inside a class method, using cls(...) instead of the class name directly supports inheritance:

class Admin(User):
    pass

admin = Admin.guest("Jordan")
print(type(admin))

This creates an Admin object, not a User object, because cls refers to the class used to call the method.

Step by Step Execution

Consider this code:

class Counter:
    total_created = 0

    def __init__(self):
        Counter.total_created += 1

    @classmethod
    def how_many(cls):
        return cls.total_created

    @staticmethod
    def add(a, b):
        return a + b

Now run:

c1 = Counter()
c2 = Counter()
print(Counter.how_many())
print(Counter.add(3, 4))

Step by step

1. c1 = Counter()

  • Python creates a new Counter object.
  • __init__ runs.
  • Counter.total_created becomes 1.

2. c2 = Counter()

  • Another Counter object is created.
  • __init__ runs again.
  • Counter.total_created becomes 2.

3. Counter.how_many()

  • Because how_many has @classmethod, Python passes the class Counter as the first argument.
  • So this is roughly like:
Counter.how_many(Counter)
  • Inside the method, cls.total_created is 2.
  • The method returns 2.

4. Counter.add(3, 4)

  • Because add has @staticmethod, Python passes nothing automatically.
  • It behaves like a regular function stored inside the class namespace.
  • It returns 7.

Key observation

  • how_many knows about the class.
  • add does not know about the class or any object.
  • A normal instance method would need an object first.

Real World Use Cases

When instance methods are used

  • Updating a shopping cart item
  • Changing a user's password
  • Formatting data from a specific record
  • Reading or modifying object state

When class methods are used

  • Alternative constructors
    • Create an object from JSON, CSV, environment variables, or database rows
  • Working with class-level configuration
    • Access shared settings or counters
  • Inheritance-friendly factories
    • Return the correct subclass automatically using cls(...)

Example:

class Config:
    def __init__(self, host, port):
        self.host = host
        self.port = port

    @classmethod
    def from_dict(cls, data):
        return cls(data["host"], data["port"])

When static methods are used

  • Validation helpers
  • Formatting helpers
  • Conversion logic closely related to a class
  • Utility functions that make sense to keep near the class

Example:

class Email:
    @staticmethod
    def is_valid(address):
        return "@" in address

This function is related to emails, so placing it inside Email can improve organization.

Take Quiz

Real Codebase Usage

In real projects, developers often choose between these method types based on what the method depends on.

Common patterns

Instance methods for object behavior

class Order:
    def __init__(self, items):
        self.items = items

    def total(self):
        return sum(item["price"] for item in self.items)

This uses self.items, so it should be an instance method.

Class methods as alternative constructors

class Product:
    def __init__(self, name, price):
        self.name = name
        self.price = price

    @classmethod
    def from_string(cls, text):
        name, price = text.split(",")
        return cls(name, float(price))

This is very common in codebases that parse files, API responses, or configuration values.

Static methods for validation and transformation

class PasswordRules:
    @staticmethod
    def long_enough(password):
        return len(password) >= 8

Guard clauses and validation

A static method is often used for small checks:

class User:
    @staticmethod
    def is_valid_age(age):
        return isinstance(age, int) and age >= 0

Inheritance-friendly factories

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

    @classmethod
    def unnamed(cls):
        return cls("Unknown")

class Dog(Animal):
    pass

pet = Dog.unnamed()

Because unnamed uses cls, calling it on Dog creates a Dog.

Practical rule

Ask this question:

  • Does it need object data? Use an instance method.
  • Does it need class data or create objects? Use a class method.
  • Does it need neither, but still belong conceptually to the class? Use a static method.

Common Mistakes

1. Using @staticmethod when you need class access

Broken code:

class Report:
    format_type = "PDF"

    @staticmethod
    def default_format():
        return cls.format_type

Problem:

  • cls does not exist in a static method.

Fix:

class Report:
    format_type = "PDF"

    @classmethod
    def default_format(cls):
        return cls.format_type

2. Forgetting self in an instance method

Broken code:

class User:
    def greet():
        return "Hello"

Problem:

  • Instance methods automatically receive the object.
  • Python will raise a TypeError when called on an instance.

Fix:

class User:
    def greet(self):
        return "Hello"

3. Using the class name instead of cls inside a class method

Less flexible code:

class Person:
    @classmethod
    def anonymous(cls):
        return Person("Anonymous")

Problem:

  • This can break inheritance expectations.

Better:

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

    @classmethod
    def anonymous(cls):
        return cls("Anonymous")

4. Using @classmethod when a normal function would be clearer

Not every helper needs to be inside a class.

class MathTools:
    @classmethod
    def add(cls, a, b):
        return a + b

If the method does not use cls, self, or class organization meaningfully, a plain function may be better.

5. Thinking @classmethod is mainly about inheritance

@classmethod does work well with inheritance, but that is not its only purpose. It mainly means: the method receives the class instead of an instance.

Inheritance is a useful consequence, not the whole definition.

Comparisons

Method types compared

Method typeDecoratorFirst automatic argumentCan access instance data?Can access class data?Common use
Instance methodNoneselfYesYes, through self or class nameNormal object behavior
Class method@classmethodclsNot directlyYesAlternative constructors, class-level behavior
Static method@staticmethodNoneNoNo automatic accessUtility helpers related to the class

Instance method vs class method

QuestionInstance methodClass method
Works on one specific object?YesNo
Can create objects using cls(...)?NoYes
Best for object state?YesNo
Best for shared class logic?SometimesYes

Static method vs plain function

OptionWhen to use it
Static methodWhen the function is strongly related to the class domain
Plain functionWhen the logic is general-purpose and not tied to the class

Important comparison with normal methods

If you write this:

class Example:
    def hello(self):
        return "hi"

Python treats hello as an instance method. That means calling obj.hello() passes obj automatically as self.

If you do not want that behavior, you must use @classmethod or @staticmethod depending on your goal.

Take Quiz

Cheat Sheet

Quick reference

Instance method

class A:
    def method(self):
        pass
  • Default method type
  • Receives self
  • Use for object-specific behavior

Class method

class A:
    @classmethod
    def method(cls):
        pass
  • Receives cls
  • Use for class-level logic
  • Great for alternative constructors
  • Prefer cls(...) over hardcoding the class name

Static method

class A:
    @staticmethod
    def method(x, y):
        pass
  • Receives no automatic first argument
  • Use for helper logic related to the class
  • Cannot use self or cls unless passed manually

Rules of thumb

  • Needs instance data? → instance method
  • Needs class data or creates instances? → class method
  • Needs neither, but belongs near the class? → static method

Common names

  • self for instance methods
  • cls for class methods

Edge case reminder

A static method is not the same as a class method.

  • @classmethod gets the class automatically
  • @staticmethod gets nothing automatically

FAQ

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

A class method receives the class as cls. A static method receives no automatic argument at all. Use a class method when the logic depends on the class; use a static method when it does not.

Why use @classmethod instead of a normal method?

Use @classmethod when the method should work with the class itself rather than with one object instance. This is common for alternative constructors such as from_dict() or from_string().

Why use @staticmethod at all?

It helps group related helper logic inside a class. This can improve code organization when the function is clearly tied to the class concept.

Can a class method access instance variables?

Not directly. It receives cls, not self. It can only access class-level data unless you pass an instance manually.

Can a static method access class variables?

Not automatically. A static method does not receive cls or self. It can still access a class by name, but that removes some flexibility.

Is @classmethod inherited by subclasses?

Yes. Subclasses inherit class methods, and when a subclass calls one, cls refers to that subclass.

Should I always use @staticmethod for helper functions?

No. If the helper is general-purpose and not really part of the class concept, a plain function outside the class is often clearer.

What happens if I leave off @classmethod or @staticmethod?

Then Python treats the method as a normal instance method, which means it expects an instance and passes self automatically when called on an object.

Take Quiz

Mini Project

Description

Build a small Book class that demonstrates all three method types. This project shows how one class can store object data, create objects in multiple ways, and keep related helper logic organized.

Goal

Create a Book class with an instance method, a class method, and a static method, then use each one correctly.

Requirements

  • Create a Book class with title and author attributes.
  • Add an instance method that returns a readable description of the book.
  • Add a class method that creates a Book from a single string like "Dune|Frank Herbert".
  • Add a static method that checks whether a title is non-empty.
  • Create at least two Book objects and call all three method types.
Take Quiz

Keep learning

Related questions

View more