初窥Python(五)——python中的decorator
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了初窥Python(五)——python中的decorator,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2592字,纯文字阅读大概需要4分钟。
内容图文
1. 介绍
decorator是用来在代码运行期间动态增加功能的,本质上是一个返回函数的高阶函数。假设现在有这样一种需求,即在每个函数调用前记录日志,记录被调用的函数名称,可以这样实现:
def log(func): def wrapper(*args, **kwargs): print "CALL %s()" % func.__name__ return func(*args, **kwargs) return wrapper def sayHi(): print "Hi, Buddy." def sayHello(): print "Hello, Buddy." # 调用函数,记录日志 log(sayHi)() # 输出为 # CALL sayHi() # Hi, Buddy. log(sayHello)() # 输出为 # CALL sayHello() # Hello, Buddy.
这种方法确实实现了记录日志的功能,但每次这么调用未免太过繁琐,decorator因此出现。
2. 使用
其实,之前定义的log
函数即为一个decorator,只是使用方式不正确:
@log def sayHi(): print "Hi, Buddy." sayHi() # 输出为 # CALL sayHi() # Hi, Buddy. @log def sayHello(): print "Hello, Buddy." sayHello() # 输出为 # CALL sayHello() # Hello, Buddy.
可以看到,使用decorator非常简单方便,def sayHi():
前的@log
相当于将sayHi
作为参数传入log
函数中,并将返回值赋给sayHi
,即:
sayHi = log(sayHi)
但是细心的读者不难发现,这样一来函数sayHi
的__name__
属性发生变化,由之前的sayHi
变为wrapper
,使用python内置的functools.wraps
方法可以解决这一问题,改造后的decorator如下:
import functools def log(func): @functools.wraps(func) def wrapper(*args, **kwargs): print "CALL %s()" % func.__name__ return func(*args, **kwargs) return wrapper
让我们更进一步,使用三层嵌套的decorator,允许再多传入一次参数:
import functools def log(text="CALL") def decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): print "%s %s()" % (text, func.__name__) return func(*args, **kwargs) return wrapper return decorator
这次我们可以选择传入一个表示函数运行状态的字符串,由于多了一层嵌套,使用时也会有些变化:
@log("EXECUTE") def sayHi(): print "Hi, Buddy." sayHi() # 输出为 # EXECUTE sayHi() # Hi, Buddy.
修改过后嵌套使用为:
sayHi = log("EXECUTE")(sayHi)
3. 拓展
3.1
修改log
函数,使该decorator既可以通过
@log
使用,又可以通过
@log("EXECUTE")
使用:
import functools def log(text="CALL"): if callable(text): func = text @functools.wraps(func) def wrapper(*args, **kwargs): print "CALL %s()" % func.__name__ return func(*args, **kwargs) else: def decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): print "%s %s()" % (text, func.__name__) return func(*args, **kwargs) return wrapper return decorator
两种使用方式:
@log def sayHi(): print "Hi, Buddy." sayHi() # 输出为 # CALL sayHi() # Hi, Buddy. @log("EXECUTE") def sayHello(): print "Hello, Buddy." sayHello() # 输出为 # EXECUTE sayHello() # Hello, Buddy.
3.2
修改log
函数,使该decorator在函数调用前及函数调用后分别输出一条日志:
import functools def log(func): def wrapper(*args, **kwargs): print "CALL BEGINNING" call = func(*args, **kwargs) print "CALL ENDING" return call return wrapper
使用该decorator:
@log def sayHi(): print "Hi, Buddy." sayHi() # 输出为 # CALL BEGINING # Hi, Buddy. # CALL ENDING
参考资料:
本文出自 “细桶假狗屎” 博客,请务必保留此出处http://xitongjiagoushi.blog.51cto.com/9975742/1683554
原文:http://xitongjiagoushi.blog.51cto.com/9975742/1683554
内容总结
以上是互联网集市为您收集整理的初窥Python(五)——python中的decorator全部内容,希望文章能够帮你解决初窥Python(五)——python中的decorator所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。