Python decorator

在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)

本质上,decorator就是一个返回函数的高阶函数,它可以让函数在不变动任何代码的前提下增加额外功能。装饰器的返回值也是函数。它经常用于:插入日志,性能测试,事务处理,缓存,权限校验等场景。有了装饰器我们就可以抽离出大量与函数功能本身无关的代码并继续重用。概括的讲,装饰器就是为已经存在的对象添加额外的功能。

 

下面的例子是在调用函数f前后增加打印日志的功能

#!python2
#-*- coding:utf-8 -*-



def f():
    print "Call function f"
    
f1=f
f1()

#查看函数对象的名字
f.__name__
f1.__name__

#导入functools模块
#因为经过装饰的函数它们的__name__变成了decorator里面的函数名字,对于
#这个例子就是write_ahead
#为了把原始函数名字等属性复制到write_ahead中我们使用@functools.wraps(func)
#这样就可以避免类似write_ahead.__name__ = func.__name__的代码


import functools

#定义一个decorator,接受函数f为参数

def log(func):
    @functools.wraps(func)
    def write_ahead(*args,**kw):
        print "Will Call %s" % f.__name__
        func(*args,**kw)
        print "After call func:"
        
    return write_ahead

#用@把decorator置于函数f定义处

@log
def f():
    print "Call function f"

f1=f
f.__name__
f1.__name__

#调用函数f不仅会调用f本身还会在其前后打印log
#相当于 f=log(f)

f1()



#下面是接受参数的decorator写法


import functools

def log(text):
    def decorator(func):
        @functools.wraps(func)
        def write_ahead(*args,**kw):
            print "Will Call %s with %s" % (f.__name__,text)
            func(*args,**kw)
            print "After call func:"
        return write_ahead
    return decorator

@log("sss")
def f():
    print "Call function f"

f1=f
f.__name__
f1.__name__
f1()



#把以上俩种整合

def log(obj):
    
    if isinstance(obj,str):
        
        text=obj
        
        def decorator(func):
            @functools.wraps(func)
            def write_ahead(*args,**kw):
                print "Will Call %s with %s" % (f.__name__,text)
                func(*args,**kw)
                print "After call func:"
            return write_ahead
        return decorator
    
    else:
        
        func=obj
        @functools.wraps(func)
        def write_ahead(*args,**kw):
            print "Will Call %s" % f.__name__
            func(*args,**kw)
            print "After call func:"
        return write_ahead
        
@log
def f():
    print "Call function f"

f1=f
f.__name__
f1.__name__
f1()


@log("sss")
def f():
    print "Call function f"

f1=f
f.__name__
f1.__name__
f1()
#class decorator

class c_d(object):
    def __init__(self,func):
        self._func=func
        
    def __call__(self):
        print "class decorator is running"
        self._func()
        print "class decorator is ending"
        
@c_d

def test():
    print "call test func"
    
test()
#装饰器顺序

@a
@b
@c

def f():
    
等价于

f=a(b(c(f)))

 

#装饰器带类参数

class locker:
    def __init__(self):
        print("locker.__init__() should be not called.")
         
    @staticmethod
    def acquire():
        print("locker.acquire() called.(这是静态方法)")
         
    @staticmethod
    def release():
        print("  locker.release() called.(不需要对象实例)")
 
def deco(cls):
    '''cls 必须实现acquire和release静态方法'''
    def _deco(func):
        def __deco():
            print("before %s called [%s]." % (func.__name__, cls))
            cls.acquire()
            try:
                return func()
            finally:
                cls.release()
        return __deco
    return _deco
 
@deco(locker)
def myfunc():
    print(" myfunc() called.")
 
myfunc()
myfunc()
class mylocker:
    def __init__(self):
        print("mylocker.__init__() called.")
         
    @staticmethod
    def acquire():
        print("mylocker.acquire() called.")
         
    @staticmethod
    def unlock():
        print("  mylocker.unlock() called.")
 
class lockerex(mylocker):
    @staticmethod
    def acquire():
        print("lockerex.acquire() called.")
         
    @staticmethod
    def unlock():
        print("  lockerex.unlock() called.")
 
def lockhelper(cls):
    '''cls 必须实现acquire和release静态方法'''
    def _deco(func):
        def __deco(*args, **kwargs):
            print("before %s called." % func.__name__)
            cls.acquire()
            try:
                return func(*args, **kwargs)
            finally:
                cls.unlock()
        return __deco
    return _deco
    
    
class example:
    @lockhelper(mylocker)
    def myfunc(self):
        print(" myfunc() called.")
 
    @lockhelper(mylocker)
    @lockhelper(lockerex)
    def myfunc2(self, a, b):
        print(" myfunc2() called.")
        return a + b
 
if __name__=="__main__":
    a = example()
    a.myfunc()
    print(a.myfunc())
    print(a.myfunc2(1, 2))
    print(a.myfunc2(3, 4))
    

 

下面的例子也不错

http://www.cnblogs.com/SeasonLee/archive/2010/04/24/1719444.html

posted on 2017-03-08 15:25  大大的橙子  阅读(368)  评论(0编辑  收藏  举报

导航