Python 装饰器原理、定义与用法详解
本文实例讲述了Python装饰器原理、定义与用法。分享给大家供大家参考,具体如下:
Python装饰器
一、何为装饰器
1、在函数中定义函数
在函数中定义另外的函数,就是说可以创建嵌套的函数,例子如下
defsayHi(name="hjj2"): print'insidesayHi()func' defgreet(): return'insidegreet()func' print(greet()) sayHi() #output #insidesayHi()func #insidegreet()func
2、将函数作为参数传给另外一个函数,装饰器原型
defsayHi(): return'hihjj2' defdoSthBeforeSayHi(func): print'beforesayHifunc' print(func()) doSthBeforeSayHi(sayHi) #output #beforesayHifunc #hihjj2
3、实现一个装饰器
在第二步中,我们已经基本探究到装饰器的原理了,python装饰器做的事就是通过封装一个函数并且用这样或那样的方式来修改它的行为。不带@的初步示例如下:
defnew_decorator(func): defwrapDecorator(): print'beforefunc' func() print'afterfunc' returnwrapDecorator deffunc_require_decorator(): print'afuncneeddecorator' func_require_decorator() #ouput:afuncneeddecorator func_require_decorator=new_decorator(func_require_decorator) func_require_decorator() #ouput: #beforefunc #afuncneeddecorator #afterfunc
使用@来运行装饰器
@new_decorator func_require_decorator() #ouput: #beforefunc #afuncneeddecorator #afterfunc
这里我们可以看到,这两个例子的运行结果是一样的。所以我们能想象得到@new_decorator的作用就是
func_require_decorator=new_decorator(func_require_decorator)
我们继续优化这个装饰器,现在我们有一个问题就是,如果我们想要通过print(func_require_decorator.__name__)就会报错#Output:wrapTheFunction。这样就需要借助python提供的functools.wraps来解决了
@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。
fromfunctoolsimportwraps defnew_decorator(func): @wraps(func) defwrapDecorator(): print'beforefunc' func() print'afterfunc' returnwrapDecorator deffunc_require_decorator(): print'afuncneeddecorator' @new_decorator func_require_decorator() print(func_require_decorator.__name__) #ouput:func_require_decorator
二、使用场景
1、授权,大体例子
fromfunctoolsimportwraps defrequires_auth(f): @wraps(f) defdecorated(*args,**kwargs): auth=request.authorization ifnotauthornotcheck_auth(auth.username,auth.password): authenticate() returnf(*args,**kwargs) returndecorated
2、日志:
fromfunctoolsimportwraps deflogit(logfile='out.log'): deflogging_decorator(func): @wraps(func) defwrapped_function(*args,**kwargs): log_string=func.__name__+"wascalled" print(log_string) withopen(logfile,'a')asopened_file: opened_file.write(log_string+'\n') returnfunc(*args,**kwargs) returnwrapped_function returnlogging_decorator @logit() deffunc1(): pass func1()
3、其他如flask中的@app.route()
三、装饰器类
1、将上面的日志装饰器变为类的初步模型如下
fromfunctoolsimportwraps classlogit(object): def__init__(self,logfile='out.log'): self.logfile=logfile def__call__(self,func): @wraps(func) defwrapped_function(*args,**kwargs): log_string=func.__name__+"wascalled" print(log_string) #打开logfile并写入 withopen(self.logfile,'a')asopen_file: #将日志写到指定文件 open_file.write(log_string+'\n') #发送一个通知 self.notify() returnfunc(*args,**kwargs) returnwrapped_function defnotify(self): pass @logit() defmyfunc1(): pass classemail_logit(logit): ''' 实现在函数调用时发送email ''' def__init__(self,email='admin@xxx.com',*args,**kwargs): self.email=email super(email_logit,self).__init__(*args,**kwargs) defnotify(self): ''' 发送邮件通知 ''' pass
通过这种方式,我们可以定义我们在自己的需求,减少代码的冗余,提高复用率。
至此,关于装饰器的探索就结束啦。
更多关于Python相关内容感兴趣的读者可查看本站专题:《Python面向对象程序设计入门与进阶教程》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python编码操作技巧总结》及《Python入门与进阶经典教程》
希望本文所述对大家Python程序设计有所帮助。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。