Python的装饰器用法学习笔记
在python中常看到在定义函数是使用@func.这就是装饰器,装饰器是把一个函数作为参数的函数,常常用于扩展已有函数,即不改变当前函数状态下增加功能.
defrun(): print"I'mrun."
我有这么一个函数,我想知道这个函数什么时候开始什么时候结束.我应该这么写
defrun(): printtime.ctime() print"I'mrun." printtime.ctime()
但是如果不允许修改函数的话就需要装饰器了
defcount(func): defwrapper(): printtime.ctime() ret=func() printtime.ctime() returnret returnwrapper @count defrun(): print"I'mrun." #print'2015-4-10'
eg:
defnow(): print'2015-4-10' f=now f()
函数有一个__name__对象可通过dir(func)func为定义的函数名
now.__name__#print'now' f.__name__#print'now' printf#print'<functionnowat0x000000000213A908>' printnow#print'<functionnowat0x000000000213A908>'
我们通过装饰器打印log日志
deflog(func): defwrapper(*args,**kwargs): print"call%s()"%func.__name__ returnfunc(*args,**kwargs) returnwrapper @log defnow(): print'2015-4-10' now()#print'callnow()'
其实装饰器修饰函数相当于,now=log(now)也就是装饰器函数把被修饰的函数当参数后赋给同名的变量
functools.wraps函数
当我们使用了装饰器后now的__name__值发生了改变
#没有使用前 now.__name__#print'now' #使用后 now.__name__#print'wrapper'
当我们使用装饰器前,now.__name__使用的是当前now函数,但使用后now这个函数其实是log(now)也就是log函数的返回值也就是被包裹的wrapper.解决方法是functools.wraps函数.
装饰闭包,使用前得调用importfunctools
deflog(func): @functools.wraps(func) defwrapper(*args,**kwargs): ...
带参数的装饰器
如果decorator需要传入参数,那就需要在写一个返回decorator的高阶函数.写出来更复杂.
deflogin(level): def_deco(func): defwrapper(*args,**kwargs): iflevel>=5: print'用户VIP等级%d'%int(level-5) else: print'用户屌丝等级%d'%abs(level-5) returnfunc(*args,**kwargs) returnwrapper return_deco @login(5) defuser(username): print'welcome,%s'%username #用户vip等级0 #welcome,mink user('mink')
带参数的decorator等于func=装饰器函数(装饰器参数)(func)
装饰器类
通过类的__call__可以想使用函数一样使用类
classA(object): def__init__(self,func): self.func=func def__call__(self): returnself.func()**2 @A deffoo(): return10 printfoo()#print100