Question
Python @classmethod vs @staticmethod Explained for Beginners
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:
-
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.
-
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.
- Marked with
-
Static methods
- Marked with
@staticmethod. - Do not receive
selforclsautomatically. - Used when the function logically belongs inside the class, but does not need instance data or class data.
- Marked with
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.
@classmethodtells Python: "Pass the class as the first argument."@staticmethodtells Python: "Do not pass anything automatically."
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 objectcls= this class@staticmethod= no automatic object or class argument
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}"
():
cls(name, role=)
():
(name, ) (name.strip()) >
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
Counterobject. __init__runs.Counter.total_createdbecomes1.
2. c2 = Counter()
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(...)
- Return the correct subclass automatically using
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:
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))
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:
clsdoes 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.
Comparisons
Method types compared
| Method type | Decorator | First automatic argument | Can access instance data? | Can access class data? | Common use |
|---|---|---|---|---|---|
| Instance method | None | self | Yes | Yes, through self or class name | Normal object behavior |
| Class method | @classmethod | cls | Not directly | Yes | Alternative constructors, class-level behavior |
| Static method | @staticmethod | None | No |
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
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 inherited by subclasses?
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
Bookclass withtitleandauthorattributes. - Add an instance method that returns a readable description of the book.
- Add a class method that creates a
Bookfrom a single string like"Dune|Frank Herbert". - Add a static method that checks whether a title is non-empty.
- Create at least two
Bookobjects and call all three method types.
Keep learning
Related questions
@staticmethod vs @classmethod in Python Explained
Learn the difference between @staticmethod and @classmethod in Python with clear examples, use cases, mistakes, and a mini project.
Call a Function by Name in a Python Module
Learn how to call a function by name in a Python module using strings, getattr, and safe patterns for dynamic function dispatch.
Catch Multiple Exceptions in One except Block in Python
Learn how to catch multiple exceptions in one Python except block using tuples, with examples, mistakes, and real-world usage.