在代码运行期间动态增加功能的方式,称之为“装饰器”(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