Python has two decorators @staticmethod and @classmethod. Could someone one explain the difference between the two or point me to a source where it is documented? When should the staticmethod decorator be used over the classmethod decorator?
views:
597answers:
4Here is a short article on this question
@staticmethod function is nothing more than a function defined inside a class. It is callable without instantiating the class first. It’s definition is immutable via inheritance.
@classmethod function also callable without instantiating the class, but its definition follows Sub class, not Parent class, via inheritance. That’s because the first argument for @classmethod function must always be cls (class).
Maybe a bit of example code will help: Notice the difference in the call signatures of foo, class_foo and static_foo:
class A(object):
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
a=A()
Below is the usual way an object instance calls a method. The object instance, a, is implicitly passed as the first argument.
a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>,1)
With classmethods, the class of the object instance is implicitly passed as the first argument instead of self.
a.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)
You can also call class_foo using the class. In fact, if you define something to be
a classmethod, it is probably because you intend to call it from the class rather than from a class instance. A.foo(1) would have raised a TypeError, but A.class_foo(1) works just fine:
A.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)
Next time you reach for the @classmethod decorator, however, this statement by Guido van Rossum might give you reason to pause:
Ironically, there are now no known uses for class methods in the Python distribution.... I might even get rid of classmethod in a future release if no good use for it can be found!
With staticmethods, neither self (the object instance) nor cls (the class) is implicitly passed as the first argument.
a.static_foo(1)
# executing static_foo(1)
foo is just a function, but when you call a.foo you don't just get the function, you get a "curried" version of the function with the object instance "a" bound as the first argument to the function. foo expects 2 arguments, while a.foo only expects 1 argument.
"a" is bound to foo. That is what is meant by the term "bound" below:
print(a.foo)
# <bound method A.foo of <__main__.A object at 0xb7d52f0c>>
With a.class_foo, "a" is not bound to foo, rather the class A is bound to foo.
print(a.class_foo)
# <bound method type.class_foo of <class '__main__.A'>>
Here, with a staticmethod, even though it is a method, a.static_foo just returns a good 'ole function with no arguments bound. static_foo expects 1 argument, and a.static_foo expects 1 argument too.
print(a.static_foo)
# <function static_foo at 0xb7d479cc>
Official python docs:
A class method receives the class as implicit first argument, just like an instance method receives the instance. To declare a class method, use this idiom:
class C: @classmethod def f(cls, arg1, arg2, ...): ... The @classmethod form is a function decorator – see the description of function definitions in Function definitions for details.
It can be called either on the class (such as C.f()) or on an instance (such as C().f()). The instance is ignored except for its class. If a class method is called for a derived class, the derived class object is passed as the implied first argument.
Class methods are different than C++ or Java static methods. If you want those, see staticmethod() in this section.
A static method does not receive an implicit first argument. To declare a static method, use this idiom:
class C: @staticmethod def f(arg1, arg2, ...): ... The @staticmethod form is a function decorator – see the description of function definitions in Function definitions for details.
It can be called either on the class (such as C.f()) or on an instance (such as C().f()). The instance is ignored except for its class.
Static methods in Python are similar to those found in Java or C++. For a more advanced concept, see classmethod() in this section.
In the lecture Advanced Python or Understanding Python, (also on YouTube), Thomas Wouters says, 43 minutes in, that classmethods are very useful, but that staticmethods are generally not, except when injecting external functions into classes, to prevent them becoming methods.