Question
@staticmethod vs @classmethod in Python Explained
Question
In Python, what is the difference between a method decorated with @staticmethod and one decorated with @classmethod?
For example, how do these two method types differ in:
- how they are defined
- what arguments they receive automatically
- when they should be used
- how they behave when called from a class or an instance
Short Answer
By the end of this page, you will understand how @staticmethod and @classmethod work in Python, what each one receives automatically, when to use each, and how they differ from regular instance methods. You will also see practical examples, common mistakes, and a small project that makes the distinction easy to remember.
Concept
In Python, methods inside a class are not all the same. The main difference between @staticmethod and @classmethod is what Python passes to them automatically.
A quick reminder of the three common method types:
- Instance method: works with a specific object and receives
self - Class method: works with the class itself and receives
cls - Static method: receives nothing automatically
Instance method
A normal method inside a class usually looks like this:
class User:
def greet(self):
return "Hello"
When you call user.greet(), Python automatically passes the instance as the first argument. That first argument is usually named self.
Class method
A class method is defined with @classmethod:
class User:
@classmethod
def from_name(cls, name):
return cls()
When you call User.from_name("Sam"), Python automatically passes the class itself as the first argument. That argument is usually named cls.
This is useful when the method needs to:
- create instances in an alternative way
- access or modify class-level data
- work correctly with inheritance
Static method
A static method is defined with @staticmethod:
class User:
@staticmethod
def is_valid_name(name):
return len(name) > 0
When you call User.is_valid_name("Sam"), Python does not pass self or cls. It behaves like a regular function placed inside the class namespace.
This is useful when the function:
- logically belongs to the class
- does not need instance data
- does not need class data
Why this matters
Choosing the correct method type makes code easier to understand.
- Use an instance method when you need object-specific data
- Use a class method when you need class-level behavior
- Use a static method when you want a utility function grouped with the class
In real programs, this affects readability, inheritance behavior, object creation patterns, and how reusable your code is.
Mental Model
Think of a class like a company.
- An instance method talks to one employee: it gets
self - A class method talks to the company itself: it gets
cls - A static method is just a tool kept in the company office: it does not get either one automatically
Simple analogy
self= this specific objectcls= this class@staticmethod= a helper function stored inside the class because it belongs there conceptually
For example:
- "What is this user's email?" → instance method
- "Create a user from a CSV row" → class method
- "Check whether an email format looks valid" → static method
A good question to ask is:
Does this method need the object, the class, or neither?
- Needs the object → instance method
- Needs the class → class method
- Needs neither → static method
Syntax and Examples
Core syntax
class Example:
def instance_method(self):
return "instance"
@classmethod
def class_method(cls):
return "class"
@staticmethod
def static_method():
return "static"
Example: all three together
class Temperature:
scale = "Celsius"
def __init__(self, value):
self.value = value
def describe(self):
return f"{self.value} degrees {self.scale}"
@classmethod
def freezing_point(cls):
return cls(0)
@staticmethod
def celsius_to_fahrenheit(celsius):
return (celsius * 9 / 5) + 32
weather = Temperature(25)
print(weather.describe())
print(Temperature.freezing_point().describe())
print(Temperature.celsius_to_fahrenheit(25))
Output:
25 degrees Celsius
0 degrees Celsius
77.0
What each method is doing
describe(self)
- Uses instance data:
self.value - Also accesses
self.scale - This should be an instance method
freezing_point(cls)
- Uses
clsto create and return an object - This is a common class method pattern called an alternative constructor
- If the class is subclassed,
cls(...)creates the correct subclass instance
celsius_to_fahrenheit(celsius)
- Does not need
selforcls - It is just a helper function related to temperatures
- This is a good use of
@staticmethod
Calling from class and instance
class Demo:
@classmethod
def show_class(cls):
return cls.__name__
@staticmethod
def show_text():
return "hello"
d = Demo()
print(Demo.show_class())
print(d.show_class())
print(Demo.show_text())
print(d.show_text())
Both @classmethod and @staticmethod can be called from:
- the class
- an instance
But their meaning is different:
- class method still receives the class automatically
- static method still receives nothing automatically
Step by Step Execution
Consider this example:
class Book:
category = "General"
def __init__(self, title):
self.title = title
@classmethod
def default_book(cls):
return cls("Untitled")
@staticmethod
def is_valid_title(title):
return len(title.strip()) > 0
Now trace these calls:
book = Book.default_book()
valid = Book.is_valid_title("Python Basics")
Step by step
1. Python reads the class definition
It creates the Book class.
categorybecomes a class attribute__init__becomes an instance methoddefault_bookbecomes a class methodis_valid_titlebecomes a static method
2. Book.default_book() is called
book = Book.default_book()
Because default_book is a class method:
- Python automatically passes
Bookascls - So inside the method,
clsrefers toBook
The method runs:
return cls("Untitled")
That becomes:
return Book("Untitled")
This creates a new Book object with:
self.title = "Untitled"
Now book stores that new instance.
3. Book.is_valid_title("Python Basics") is called
valid = Book.is_valid_title("Python Basics")
Because is_valid_title is a static method:
- Python does not pass
self - Python does not pass
cls - Only the argument you provide is used
So the method receives:
title = "Python Basics"
It evaluates:
len(title.strip()) > 0
title.strip()gives"Python Basics"- its length is greater than
0 - result is
True
So valid becomes True.
Key observation
The class method can create objects using the class. The static method simply performs a related check without needing the class or an instance.
Real World Use Cases
Common uses for @classmethod
Alternative constructors
A class method is often used to create objects from different input formats.
class User:
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def from_dict(cls, data):
return cls(data["name"], data["age"])
Useful when reading:
- JSON data from an API
- rows from a CSV file
- configuration files
- database records
Class-level configuration
class AppConfig:
debug = False
@classmethod
def enable_debug(cls):
cls.debug = True
This affects the class itself, not one specific object.
Common uses for @staticmethod
Validation helpers
class User:
@staticmethod
def is_valid_age(age):
return age >= 0
Conversion or formatting logic
class DateTools:
@staticmethod
def format_year(year):
return f"Year: {year}"
Utility logic grouped with a class
Sometimes a function belongs conceptually near a class even though it does not need class state.
class PasswordRules:
@staticmethod
def has_min_length(password):
return len(password) >= 8
In apps and APIs
@classmethodis useful for creating model objects from API responses@staticmethodis useful for input checks and transformation helpers@classmethodhelps subclasses create the correct object type@staticmethodkeeps utility logic organized without needing external helper modules for very small tasks
Real Codebase Usage
In real codebases, developers usually choose between these method types based on what the method needs to know.
Common @classmethod patterns
Alternative constructors
class Order:
def __init__(self, order_id, total):
self.order_id = order_id
self.total = total
@classmethod
def from_api(cls, payload):
return cls(payload["id"], payload["total"])
This keeps parsing logic close to the class.
Inheritance-friendly creation
class Animal:
def __init__(self, name):
self.name = name
@classmethod
def unnamed(cls):
return cls("Unknown")
class Dog(Animal):
pass
pet = Dog.unnamed()
print(type(pet).__name__)
Output:
Dog
Because cls is Dog, the returned object is a Dog, not just an Animal.
Factory-style methods
Developers often use class methods to provide named ways to create objects.
from_dictfrom_jsonfrom_stringdefaultempty
Common @staticmethod patterns
Validation helpers near the model
class Product:
@staticmethod
def is_valid_price(price):
return price >= 0
Small transformation logic
class StringTools:
@staticmethod
def slugify(text):
return text.lower().replace(" ", "-")
Guard clauses and validation
A static method is often used before object creation.
class Product:
def __init__(self, name, price):
if not self.is_valid_price(price):
raise ValueError("Price must be non-negative")
self.name = name
self.price = price
@staticmethod
def is_valid_price(price):
return price >= 0
Practical guideline
In real projects:
- use
@classmethodwhen object creation or class behavior is involved - use
@staticmethodfor related helper logic that needs no object or class context - use a normal function outside the class if the logic does not really belong to the class at all
Common Mistakes
1. Using @staticmethod when cls is needed
Broken example:
class Person:
def __init__(self, name):
self.name = name
@staticmethod
def create(name):
return cls(name)
Problem:
clsdoes not exist in a static method
Fix:
class Person:
def __init__(self, name):
self.name = name
@classmethod
def create(cls, name):
return cls(name)
2. Using @classmethod for logic that does not need the class
This works, but it is misleading:
class MathTools:
@classmethod
def add(cls, a, b):
return a + b
If the method does not use cls, prefer @staticmethod:
class MathTools:
@staticmethod
def add(a, b):
return a + b
3. Forgetting that static methods do not get self
Broken example:
class Car:
def __init__(self, brand):
self.brand = brand
@staticmethod
def show_brand():
return self.brand
Problem:
selfis not available in a static method
Fix:
class Car:
def __init__(self, brand):
self.brand = brand
def show_brand(self):
return self.brand
4. Confusing class attributes with instance attributes
class Counter:
count = 0
@classmethod
def increment(cls):
cls.count += 1
This changes the class attribute, shared across instances. It does not create separate counts per object.
5. Putting too many helpers inside classes
Sometimes beginners put every function into a class as a static method.
That can make code harder to organize.
Use a static method only when the function clearly belongs to the class. Otherwise, a normal module-level function may be better.
Comparisons
Method type comparison
| Method type | First automatic argument | Can access instance data? | Can access class data? | Common use |
|---|---|---|---|---|
| Instance method | self | Yes | Yes | Work with one object |
| Class method | cls | Not directly | Yes | Alternative constructors, class-level behavior |
| Static method | None | No | No, unless referenced manually | Utility logic related to the class |
@classmethod vs @staticmethod
| Feature | @classmethod | @staticmethod |
|---|---|---|
| Receives class automatically? | Yes, as cls | No |
| Receives instance automatically? | No | No |
| Good for creating objects? | Yes | Usually no |
| Works well with inheritance? | Yes | Not for class-aware creation |
| Good for helper functions? | Sometimes | Yes |
Which one should you choose?
| If your method needs... | Use |
|---|---|
object state like self.name | instance method |
class state or cls(...) | @classmethod |
| neither object nor class data | @staticmethod |
@staticmethod vs normal function outside the class
| Option | Best when |
|---|---|
@staticmethod | the function clearly belongs to the class conceptually |
| normal function | the function is general-purpose and not tied to one class |
Cheat Sheet
Quick rules
- Instance method: first parameter is
self - Class method: use
@classmethod, first parameter iscls - Static method: use
@staticmethod, no automatic first parameter
Syntax
class Example:
def instance_method(self):
pass
@classmethod
def class_method(cls):
pass
@staticmethod
def static_method(x, y):
return x + y
When to use which
- Use instance methods for object-specific behavior
- Use class methods for class-level behavior or alternative constructors
- Use static methods for helper logic that belongs with the class
Memory tip
self= this objectcls= this classstatic= no automatic object or class
Common pattern
class User:
def __init__(self, name):
self.name = name
@classmethod
def from_dict(cls, data):
return cls(data["name"])
@staticmethod
def is_valid_name(name):
return len(name.strip()) > 0
Important edge case
A static method can still access the class by naming it directly:
class A:
value = 10
@staticmethod
def show():
return A.value
But this is not class-aware in the same way as cls, so it is less flexible for inheritance.
Best practice
If a method does not use self or cls, ask whether it should be:
- a
@staticmethod, or - a normal function outside the class
FAQ
What is the main difference between @staticmethod and @classmethod in Python?
@classmethod receives the class as the first argument, usually named cls. @staticmethod receives no automatic first argument.
When should I use @classmethod in Python?
Use it when the method needs the class itself, especially for alternative constructors like from_dict, from_json, or default.
When should I use @staticmethod in Python?
Use it for helper functions that belong to the class logically but do not need instance or class data.
Can I call a class method on an instance?
Yes. You can call both class methods and static methods from either the class or an instance.
Can a static method access class variables?
Not automatically. It does not receive cls, but it can still refer to the class by name directly if needed.
Is @staticmethod the same as a normal function?
Not exactly. It behaves similarly because it gets no automatic arguments, but it is stored inside the class namespace.
Why is @classmethod better for inheritance?
Because it receives cls, which refers to the actual class used to call the method. That allows subclass-aware object creation.
Should I always use @staticmethod for helper methods?
No. If the function does not really belong to the class, a regular function outside the class may be cleaner.
Mini Project
Description
Build a small User class that demonstrates all three method styles: an instance method, a class method, and a static method. This project shows a realistic pattern where you validate input with a static method, create objects from external data with a class method, and display object data with an instance method.
Goal
Create a User class that can be built from a dictionary, validate email text, and describe a specific user instance.
Requirements
[ "Create a User class with name and email attributes", "Add an instance method that returns a readable description of the user", "Add a class method that creates a User from a dictionary", "Add a static method that checks whether an email contains an @ symbol", "Use all three methods in example code" ]
Keep learning
Related questions
Add Rows to a Pandas DataFrame in Python
Learn how to add rows to a Pandas DataFrame, why repeated row appends are slow, and when to use loc, concat, or record lists.
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.