What is the difference between a function decorated with @staticmethod and one decorated with @classmethod?
One pretty important practical difference occurs when subclassing. If you don't mind, I'll hijack @unutbu's example:
class A:
def foo(self, x):
print("executing foo(%s, %s)" % (self, x))
@classmethod
def class_foo(cls, x):
print("executing class_foo(%s, %s)" % (cls, x))
@staticmethod
def static_foo(x):
print("executing static_foo(%s)" % x)
class B(A):
pass
In class_foo
, the method knows which class it is called on:
A.class_foo(1)
# => executing class_foo(, 1)
B.class_foo(1)
# => executing class_foo(, 1)
In static_foo
, there is no way to determine whether it is called on A
or B
:
A.static_foo(1)
# => executing static_foo(1)
B.static_foo(1)
# => executing static_foo(1)
Note that this doesn't mean you can't use other methods in a staticmethod
, you just have to reference the class directly, which means subclasses' staticmethods will still reference the parent class:
class A:
@classmethod
def class_qux(cls, x):
print(f"executing class_qux({cls}, {x})")
@classmethod
def class_bar(cls, x):
cls.class_qux(x)
@staticmethod
def static_bar(x):
A.class_qux(x)
class B(A):
pass
A.class_bar(1)
# => executing class_qux(, 1)
B.class_bar(1)
# => executing class_qux(, 1)
A.static_bar(1)
# => executing class_qux(, 1)
B.static_bar(1)
# => executing class_qux(, 1)