So you’re deep into Python programming, and you’ve just come across @staticmethod
and @classmethod
. You might be thinking, “Wait, don’t we already have functions? Why do we need these fancy class-based versions?” Or maybe you’ve heard the buzz and want to add these Pythonic superpowers to your toolkit.
No worries. We’re going to break down the difference between these two decorators, explain when and why you should use them, and even show you how they work under the hood. And, of course, we’ll throw in some real-world use cases to help everything stick.

But first, let’s get this out of the way: both @staticmethod
and @classmethod
are used with classes, but they serve very different purposes. They’re like cousins in the decorator family—related, but with totally different vibes.
Ready to dive in? Let’s go!
@staticmethod: The Lone Wolf
A staticmethod
is exactly what it sounds like: a method that doesn’t care about the class or any instance of the class. It’s just a regular old function living inside a class, with no interest in the class’s state or any specific object. It’s the lone wolf of the class method world—it doesn’t need self
, doesn’t care about class variables, and doesn’t care about class instances. It just does its thing.
So, What’s the Point?
You might ask, “If it doesn’t need self
or access to the class, why not just create a regular function outside the class?” Good question! There are two main reasons:
Organizational clarity: Sometimes, it makes sense to group a method within a class even if it doesn’t interact with the class itself. This can help with code organization and readability. For example, if you have a utility function that’s only relevant to the class, it’s often clearer and cleaner to bundle it inside the class.
Logical grouping: It helps to logically associate the function with the class, even if it doesn’t interact with the class directly.
Example of a staticmethod
Let’s start with a simple example. Suppose we have a Car
class, and we want to add a utility method to check if a car is electric based on the type of fuel it uses. Since this method doesn’t need to access any class or instance data, we can make it a staticmethod
.
class Car:
def __init__(self, brand, model, fuel_type):
self.brand = brand
self.model = model
self.fuel_type = fuel_type
@staticmethod
def is_electric(fuel_type):
return fuel_type == 'electric'
print(Car.is_electric('electric'))
# True
print(Car.is_electric('gasoline'))
Here’s what’s going on:
is_electric()
doesn’t care about the class or the instance (self
). It only needs thefuel_type
argument to make its decision.You can call it either on the class (
Car.is_electric()
) or on an instance (my_car.is_electric()
), but the result is the same. There’s no reference toself
orcls
because it doesn’t matter.
So why put it inside the Car
class? It makes sense contextually—checking if a car is electric is a function closely related to cars, even if it doesn’t depend on any specific car object.
When to Use @staticmethod
Utility methods: These are helper functions that don’t need to modify or access class or instance state, but still logically belong within the class’s context.
Organization: When you want to keep related code together in one place for clarity.
Consistency: Even if a function doesn’t need access to the class, placing it inside the class can sometimes improve code readability and consistency.
When NOT to Use It
There are also times when we are better off without the @staticmethod.
If the method needs to access or modify class attributes or instance attributes,
@staticmethod
is not what you want. We’ll see that@classmethod
is a better fit for these cases.
That’s all that you need to work with @staticmethod. It’s there for keeping related ideas closer. Although, it doesn’t makes any use of the class instances, having it closer to the class makes it easier to debug and keep your friends closer.
Next, we head to classmethod.
@classmethod: The Team Player
Now let’s talk about @classmethod
. A classmethod
is a bit more social than the lone wolf staticmethod
. It needs a reference to the class itself (called cls
, by convention). This allows it to modify or access the class’s attributes and methods, but still not interact with individual instances.

While a regular method automatically takes self
as its first parameter (referring to the instance), a classmethod
takes cls
, which refers to the class as a whole. This distinction allows you to work at the class level rather than the instance level.
Why Use @classmethod
?
There are a few reasons why you might use @classmethod
instead of a regular method or @staticmethod
:
Access class variables: If you need to access or modify class-level data that affects all instances,
@classmethod
is the way to go.Alternative constructors: It’s a popular pattern to use
@classmethod
to define alternative ways to create an instance of the class. For example, you might want to create an object with a different set of input parameters or using some special logic.
Example of a @classmethod
Let’s extend our Car
example. Imagine that, along with the regular constructor, we also want to allow the creation of a Car
from a string input in a specific format, say "Brand-Model-FuelType"
. For that, we’ll define an alternative constructor using a @classmethod
.
class Car:
def __init__(self, brand, model, fuel_type):
self.brand = brand
self.model = model
self.fuel_type = fuel_type
@classmethod
def from_string(cls, car_string):
brand, model, fuel_type = car_string.split('-')
return cls(brand, model, fuel_type)
car1 = Car('Tesla', 'Model S', 'electric')
car2 = Car.from_string('Ford-Mustang-gasoline')
print(car1.brand)
# Tesla
print(car2.model)
# Mustang
Here’s what’s happening:
We define the class method
from_string()
with the@classmethod
decorator.It takes
cls
as the first argument, referring to theCar
class, so we can create a new instance usingcls(brand, model, fuel_type)
. This is what makesfrom_string()
an alternative constructor.Now, you can create a
Car
in two ways—by using the standard constructor or the new class methodfrom_string()
.
When to Use @classmethod
Alternative constructors: This is perhaps the most common use case for class methods. If you want to provide more than one way to create an object, a class method is ideal.
Access class-level data: If you need to access or modify class attributes (shared among all instances of the class), you should use a class method. This makes the method aware of the class it’s working with, not just a single instance.
Factory methods: If you’re implementing a factory pattern (a design pattern to create objects),
@classmethod
can be useful for creating instances with specific configurations.
@staticmethod vs @classmethod: What’s the Difference?
You might still be wondering, “Okay, but what’s the real difference between @staticmethod
and @classmethod
? They both seem to be kind of the same thing, right?"
Here’s a quick breakdown:
First argument: This is the key difference. A
@staticmethod
doesn’t take any reference to the class or instance as the first argument, while a@classmethod
always takescls
(the class) as the first argument.Use case: Use
@staticmethod
when the method doesn’t need to know about the class or instance—essentially, when you want a regular function that lives in a class. Use@classmethod
when you need to access or modify class-level variables or need alternative constructors.
Let’s break it down with another comparison:
class Example:
class_attr = "I'm a class attribute"
@staticmethod
def static_method():
return "I don't care about class or instance"
@classmethod
def class_method(cls):
return f"Class attribute is: {cls.class_attr}"
print(Example.static_method())
# I don't care about class or instance
print(Example.class_method())
# Class attribute is: I'm a class attribute
Notice the difference:
static_method()
doesn’t interact with the class in any way. It’s just a standalone function living in a class.class_method()
has access to the class itself viacls
, allowing it to interact withclass_attr
.
Interesting Use Cases of @staticmethod
and @classmethod
We will now look at some of the interesting use cases of these two decorators:
1. Alternative Constructors for Flexible Object Creation
One of the most common use cases for @classmethod
is to define alternative constructors. Imagine a class where you need to allow different ways to create objects.
For example, let’s say you’re building a User
class and want to allow users to sign up with either their username or email. You can create an alternative constructor for that:
class User:
def __init__(self, username, email):
self.username = username
self.email = email
@classmethod
def from_email(cls, email):
username = email.split('@')[0]
return cls(username, email)
user1 = User('john_doe', 'john@example.com')
user2 = User.from_email('jane@example.com')
print(user2.username)
# jane
Here, from_email()
gives us a flexible way to create User
objects from an email address, with the username extracted automatically.
2. Utility Methods in Classes
For @staticmethod
, utility functions that don’t depend on class or instance data are perfect candidates. For example, a method to validate an email format can be a static method within a User
class:
class User:
def __init__(self, username, email):
self.username = username
self.email = email
@staticmethod
def validate_email(email):
return "@" in email and "." in email
print(User.validate_email('john@example.com'))
# True
print(User.validate_email('invalid-email'))
# False
The validate_email()
method doesn’t need access to the class or its instances, making @staticmethod
the right choice.
Conclusion: Know When to Use Each
@staticmethod
and @classmethod
may seem similar at first, but they serve very distinct purposes. Understanding the difference between them will make your Python code more organized, flexible, and efficient.
Use
@staticmethod
when you don’t need to access or modify class or instance data—when the method is a utility function that fits within the class context but doesn’t rely on its state.Use
@classmethod
when you need to interact with class-level attributes or need to create alternative constructors that can initialize the class in different ways.
In the end, it’s all about writing clear, organized code that’s easy to maintain and extend. So now that you’ve unlocked the power of @staticmethod
and @classmethod
, go ahead and start applying them where they make sense in your own projects.