python built-in decorators

Built-in Decorators

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 types module to help us distinguish among the various elements of a class definition.

2

We define a superclass that includes two methods. The classmethod, getMethods, introspects a class, looking for the method functions. The ordinary instance method, help, uses the introspection to print a list of functions defined by a class.

We use the @classmethod decorator to modify the getMethods function. Making the getMethods into a class method means that the first argument will be the class object itself, not an instance.

4

Every subclass of SelfDocumenting can print a list of method functions using a help method.

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> 


 


你可能感兴趣的:(Singleton,python,factory,ClassMethod,decorators)