Static Methods, Class Methods, and Decorators

来源:互联网 发布:ttc 轴体 知乎 编辑:程序博客网 时间:2024/04/30 10:56

 

1 Using Static Methods and Class Methods

Let's start with an example:

methods.py

class MethodsTest:                  # Create an instance: obj = MethodsTest()    def imeth(self, x):             # Normal instance method: passed a self                                    # (1)Pass an instance automatically, obj.imeth("xxx")                                    # (2)Pass an instance explicitly, MethodsTest.imeth(obj, "xxx")        print("instance method", self, x)    #@staticmethod    def smeth(y):                   # Static: no instance passed                                    # It SHOULD be called through the whole class, MethodsTest.smeth("yyy")                                    # But it can be called through an instance, Test().smeth("yyy")        print("static method", y)    #@classmethod                                                                                               def cmeth(cls, z):              # Class: gets class, not instance                                    # (1)Pass a class automatically, MethodsTest.cmeth("zzz")                                    # (2)Pass a class explicitly, MethodsTest.cmeth(anotherClass, "zzz")        print("class method", cls, z)    smeth = staticmethod(smeth)     # Make smeth a static mehod    cmeth = classmethod(cmeth)      # Make cmeth a class method



通过静态方法对比属性:

Python的类中,如果一个属性是在方法外面定义的,如:

class Attr:    attr1 = 0    ...   

此时属性attr1是属于整个类的,但类的实例也是可以访问的,即所有的实例共享它(相当于Java中的静态变量)。这样的attr1在类的实例的__dict__中是不存在的。

在__init__中通过self定义的变量是属于某个实例的,作用域为per instance!


2 Function Decorators

Syntactically, a function decorator is a sort of runtime declaration about the function that follows. A function decorator is coded on a line by itself just before the def statement that defines a function or method. It consists of the @ symbol, followed by what we  call  a  metafunction—a  function  (or  other  callable  object)  that  manages  another function. Static methods today, for example, may be coded with decorator syntax like this:

class C:   @staticmethod                                 # Decoration syntax   def meth():       ...

(1)Example 1

decorator1.py

class Tracer:    def __init__(self, func):        self.calls = 0        self.func = func    def __call__(self, *args):        self.calls += 1        print("call %s to %s" %(self.calls, self.func.__name__))        self.func(*args)@Tracer             # Same as spam = Tracer(spam)def spam(a, b, c):    print(a, b, c)spam(1, 2, 3)       # Really calls the Tracer wrapper objectspam('a', 'b', 'c') # Invokes __call__ in classspam(4, 5, 6)       #  __call__ adds logic and runs original object          


Because  the  spam  function  is  run  through  the  tracer  decorator,  when  the  original spam name is called it actually triggers the __call__ method in the class. This method counts and logs the call, and then dispatches it to the original wrapped function. Note how the *name argument syntax is used to pack and unpack the passed-in arguments; because of this, this decorator can be used to wrap any function with any number of positional arguments.
The net effect, again, is to add a layer of logic to the original spam function. Here is the script’s output—the first line comes from the tracer class, and the second comes from the spam function:




(2)Example 2

 The function decorator syntax:

@decoratordef func(args): ...

is automatically translated to this equivalent by Python, to rebind the function name to the result of the decorator callable:

def func(args): ...func = decorator(func)


See:
http://blog.csdn.net/songuooo/article/details/8372926       6 A Jython example


3 Class Decorators and Metaclasses

In short, class decorators are similar to function decorators, but they are run at the end of a class statement to rebind a class name to a callable. As such, they can be used to either manage classes just after they are created, or insert a layer of wrapper logic to manage instances when they are later created. Symbolically, the code structure:

def decorator(aClass): ...@decoratorclass C: ...

is mapped to the following equivalent:

def decorator(aClass): ...class C: ...C = decorator(C)

The class decorator is free to augment the class itself, or return an object that intercepts later instance construction calls.