Python has two built-in decorators.
@staticmethod
The staticmethod
decorator modifies a method function so that it does not use the self
variable. The method function will not have access to a specific instance of the class.
For an example of a static method, see the section called “Static Methods and Class Method”.
@classmethod
The classmethod
decorator modifies a method function so that it receives the class object as the first parameter instead of an instance of the class. This method function wil have access to the class object itself.
The @classmethod
decorator is used to create singleton classes. This is a Python technique for defining an object which is also a unique class. The class definition is also the one and only instance. This gives us a very handy, easy-to-read way to segregate attributes into a separate part of a class declaration. This is a technique used heavily by Python frameworks.
Generally, a function decorated with @classmethod
is used for introspection of a class. An introspection method looks at the structure or features of the class, not the values of the specific instance.
Here's a contrived example of using introspection to display some features of a object's class.
Example 26.1. introspection.py
import types class SelfDocumenting( object ): @classmethod def getMethods( aClass ): return [ (n,v.__doc__) for n,v in aClass.__dict__.items() if type(v) == types.FunctionType ] def help( self ): """Part of the self-documenting framework""" print self.getMethods() class SomeClass( SelfDocumenting ): attr= "Some class Value" def __init__( self ): """Create a new Instance""" self.instVar= "some instance value" def __str__( self ): """Display an instance""" return "%s %s" % ( self.attr, self.instVar )
We import the |
|
We define a superclass that includes two methods. The classmethod, |
|
We use the |
|
Every subclass of |
Here's an example of creating a class and calling the help method we defined. The result of the getMethods
method function is a list of tuples with method function names and docstrings.
>>>
ac= SomeClass()
>>>
ac.help()
[('__str__', 'Display an instance'), ('__init__', 'Create a new Instance')]
Difference between @staticmethod and @classmethod decorators
http://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python
A staticmethod is a method that knows nothing about the class or instance it was called on. It just gets the arguments that were passed, no implicit first argument. It is basically useless in Python -- you can just use a module function instead of a staticmethod.
A classmethod, on the other hand, is a method that gets passed the class it was called on, or the class of the instance it was called on, as first argument. This is useful when you want the method to be a factory for the class: since it gets the actual class it was called on as first argument, you can always instantiate the right class, even when subclasses are involved.
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)
One use people have found for class methods is to create inheritable alternative constructors.
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, anda.static_foo
expects 1 argument too.
print(a.static_foo) # <function static_foo at 0xb7d479cc>