@classmethod vs @staticmethod vs Plain Instance Method
Three ways to define a function inside a class. Each serves a different purpose.
class Demo:
# ── Instance method (no decorator) ──
def regular(self, x):
return f"instance: {self}.{x}"
# ── Class method ──
@classmethod
def clsmtd(cls, x):
return f"class: {cls}.{x}"
# ── Static method ──
@staticmethod
def static(x):
return f"static: {x}"Instance Method — def method(self, ...)
- Receives
self→ the instance that called it. - Can read/write instance state (
self.attr). - Needs an object to be called on (or you pass one manually).
obj = Demo()
obj.regular("hi") # instance: <Demo object>.hi
Demo.regular(obj, "hi") # same thing, explicit selfClass Method — @classmethod
- Receives
cls→ the class itself (or a subclass). - Can access/modify class-level state (
cls.attr). - Polymorphic — if a subclass calls it,
clsis the subclass.
Demo.clsmtd("hi") # class: <class 'Demo'>.hi
class Sub(Demo): pass
Sub.clsmtd("hi") # class: <class 'Sub'>.hiCommon use: alternative constructors.
class Vector:
def __init__(self, x, y):
self.x, self.y = x, y
@classmethod
def from_tuple(cls, t):
return cls(*t)
v = Vector.from_tuple((3, 4))Static Method — @staticmethod
- Receives neither
selfnorcls. - Just a plain function namespaced inside the class.
- Behaves exactly like a module-level function — no access to class or instance.
Demo.static("hi") # static: hi
obj = Demo()
obj.static("hi") # static: hi (works on instance too)Use when the function is conceptually tied to the class but doesn’t need its state (e.g. a helper or conversion that could live outside).
Quick Reference
| Decorator | First param | Bound to | Can access instance | Can access class |
|---|---|---|---|---|
| (none) | self |
instance | yes | yes (via self.__class__) |
@classmethod |
cls |
class | no | yes |
@staticmethod |
nothing | neither | no | no |
When to Use What
- Instance method — default choice. The function needs or might need instance data.
@classmethod— factory methods, or any function that needs the class (especially for subclass-friendly polymorphism).@staticmethod— the function doesn’t referenceselforclsat all. Move it to a module-level function unless it’s so closely tied to the class that namespacing it improves readability.