@staticmethod vs @classmethod
@staticmethod vs @classmethod
Section titled โ@staticmethod vs @classmethodโWhat it is
Section titled โWhat it isโBoth decorators define a method that can be called on the class itself (not just an instance), but they differ in what gets passed automatically: @classmethod receives the class (cls) as its first argument; @staticmethod receives nothing automatic at all โ itโs just a regular function that happens to live inside the classโs namespace.
Before this feature
Section titled โBefore this featureโWithout either decorator, every method is an instance method โ it requires an instance and automatically receives self. Calling it on the class instead of an instance, or needing access to the class rather than a specific instance, doesnโt work cleanly:
class Pizza: def __init__(self, size, toppings): self.size = size self.toppings = toppings
def describe(self): # instance method โ needs self return f"{self.size} pizza with {self.toppings}"
# To build a "constructor-like" helper, you'd have to hack around needing an instanceAfter this feature
Section titled โAfter this featureโclass Pizza: def __init__(self, size, toppings): self.size = size self.toppings = toppings
def describe(self): # instance method: needs an instance, gets `self` return f"{self.size} pizza with {self.toppings}"
@classmethod def margherita(cls): # alternative constructor โ gets `cls` return cls(size="medium", toppings=["tomato", "mozzarella"])
@staticmethod def is_valid_size(size): # no self, no cls โ just a namespaced utility return size in ("small", "medium", "large")
p = Pizza.margherita() # called on the class, builds an instance via cls(...)print(p.describe()) # medium pizza with ['tomato', 'mozzarella']print(Pizza.is_valid_size("large")) # True -- no instance needed at allWhy this is better
Section titled โWhy this is betterโ@classmethodfor alternative constructors:Pizza.margherita()reads as a named, discoverable way to build an instance, and โ critically โcls(...)means subclasses inherit the alternative constructor correctly (Pizza.margherita()called on a subclass builds a subclass instance, not a base-class one).@staticmethodfor logically-grouped utilities:is_valid_sizedoesnโt needselforclsat all; making it a plain module-level function would work too, but keeping it on the class groups related functionality and namespaces it (Pizza.is_valid_size(...)).- Clear intent at the call site: seeing
@classmethod/@staticmethodtells a reader immediately whether the method needs instance state, class state, or neither.
Key notes / edge cases
Section titled โKey notes / edge casesโ- Calling any of the three (
instance method,@classmethod,@staticmethod) works whether you call it via an instance or the class โ Python resolvesself/clsautomatically based on the decorator, not based on how you called it. - The key practical difference from a plain module-level function:
@staticmethodlives in the classโs namespace (Pizza.is_valid_size) and gets inherited by subclasses, but doesnโt participate in polymorphism the way@classmethoddoes. - A
@classmethodalternative constructor called on a subclass correctly returns an instance of the subclass, becauseclsis whichever class the method was actually accessed through:
class StuffedCrustPizza(Pizza): pass
p = StuffedCrustPizza.margherita()print(type(p)) # <class '__main__.StuffedCrustPizza'> -- not Pizza!Quick practice
Section titled โQuick practiceโ-
What does a
@classmethodreceive automatically as its first argument?Answer
`cls` โ the class the method was called through (which may be a subclass, not necessarily the class where the method was defined). -
Why is
@classmethodpreferred over@staticmethodfor alternative constructors?Answer
Because `cls(...)` inside the method correctly builds an instance of whatever class it was actually called on โ including subclasses โ while a `@staticmethod` would have to hardcode the class name, breaking subclassing. -
What does
@staticmethodreceive automatically?Answer
Nothing โ no `self`, no `cls`. It behaves like a plain function, just namespaced under the class.