In Python, @classmethod
and @staticmethod
are decorators used to define methods within a class, but they serve different purposes:
1. @classmethod
- First Parameter:
cls
(refers to the class itself, not an instance). - Purpose:
- Operate on the class (e.g., modify class-level variables).
- Create factory methods (alternative constructors).
- Inherit properly in subclasses (e.g.,
cls
points to the subclass when called from one). - Example:
class MyClass:
class_var = 0
@classmethod
def increment_class_var(cls):
cls.class_var += 1 # Modifies class-level variable
@classmethod
def from_string(cls, data: str):
# Factory method to create an instance from a string
return cls(data.split(","))
# Usage:
MyClass.increment_class_var() # Class variable updated
obj = MyClass.from_string("a,b,c") # Creates an instance
2. @staticmethod
- First Parameter: None (no
self
orcls
). - Purpose:
- Act as utility functions related to the class (no access to class/instance state).
- Group logically related functions under the class namespace.
- Example:
class MathUtils:
@staticmethod
def add(a: int, b: int) -> int:
return a + b # No dependency on class/instance
# Usage:
result = MathUtils.add(3, 5) # Output: 8
Key Differences
Feature | @classmethod | @staticmethod |
---|---|---|
First Parameter | cls (class reference) | None |
Access to Class | Can modify class state | No access to class/instance |
Use Cases | Factory methods, class-level logic | Utility functions, helper methods |
Inheritance | cls adapts to subclass | Behavior fixed (no cls /self ) |
When to Use Which
- Use
@classmethod
when you need to: - Create alternative constructors (e.g.,
from_json()
,from_csv()
). - Modify class-level state (e.g., counters, configurations).
- Use
@staticmethod
for functions that: - Don’t depend on class/instance state (e.g., validation, calculations).
- Are logically grouped under the class for organization.
Example: Inheritance Behavior
class Parent:
@classmethod
def create(cls):
return cls() # Uses the subclass if inherited
@staticmethod
def log(message):
print(f"Log: {message}")
class Child(Parent):
pass
# Classmethod adapts to Child:
child = Child.create() # Returns a Child instance
# Staticmethod remains unchanged:
Child.log("Hello") # Output: "Log: Hello"
By choosing the right decorator, you ensure proper access to class/instance data and maintain clean code structure.