打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
python笔记36-装饰器之wraps

前言

前面一篇对python装饰器有了初步的了解了,但是还不够完美,领导看了后又提出了新的需求,希望运行的日志能显示出具体运行的哪个函数。

namedoc

__name__用于获取函数的名称,__doc__用于获取函数的docstring内容(函数的注释)

import time def func_a(a): '''func_a --> hello''' print("hello"+a) time.sleep(0.5) return True def func_b(b, c="xx"): '''func_b --> world''' print("world"+b+c) time.sleep(0.8) return True if __name__ == '__main__': print(func_a.__name__) # 结果 func_a print(func_a.__doc__) # func_a --> hello print(func_b.__name__) # func_b print(func_b.__doc__) # func_b --> world

装饰器加函数名称日志

在装饰器里面添加2行代码,打印正在运行函数的名称和docstring内容

import time def runtime(func): '''runtime decorators''' def wrapper(*args, **kwargs): '''wrapper inner fuction''' print("running function : %s" % func.__name__) print("docstring: %s" % func.__doc__) start = time.time() f = func(*args, **kwargs) # 原函数 end = time.time() print("运行时长:%.4f 秒" % (end-start)) return f return wrapper @runtime def func_a(a): '''func_a --> hello''' print("hello"+a) time.sleep(0.5) return True @runtime def func_b(b, c="xx"): '''func_b --> world''' print("world"+b+c) time.sleep(0.8) return True if __name__ == '__main__': func_a("a") print(func_a.__name__) print(func_a.__doc__)

运行结果

running function : func_a docstring: func_a --> hello helloa 运行时长:0.5008 秒 wrapper wrapper inner fuction

从运行的结果可以看出,func_a.__name__运行的结果是wrapper,func_a.__doc__运行的结果是wrapper inner fuction。
也就是说被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变),那这个问题如何解决呢?
这就需要用到functools里面的一个wraps函数了

functools

当func_a函数被装饰后,导致了一个副作用:自身的函数属性和docstring内容变成了wrapper函数的属性了。
这里需用到functools里面的一个wraps的装饰器来消除这样的副作用。

import time from functools import wraps def runtime(func): '''runtime decorators''' @wraps(func) def wrapper(*args, **kwargs): '''wrapper inner fuction''' print("running function : %s" % func.__name__) print("docstring: %s" % func.__doc__) start = time.time() f = func(*args, **kwargs) # 原函数 end = time.time() print("运行时长:%.4f 秒" % (end-start)) return f return wrapper

只需在wrapper函数上加上@wraps(func)即可解决

运行结果

running function : func_a docstring: func_a --> hello helloa 运行时长:0.5004 秒 func_a func_a --> hello

类装饰器

带参数的装饰器,可以写成类装饰器

import time from functools import wraps class runtime(object): '''runtime class decorators''' def __init__(self, slowly=1): self.slowly = slowly def __call__(self, func): @wraps(func) def wrapper(*args, **kwargs): '''wrapper inner fuction''' print("running function : %s" % func.__name__) print("docstring: %s" % func.__doc__) start = time.time() f = func(*args, **kwargs) # 原函数 end = time.time() t = end-start time.sleep((self.slowly-1)*t) # 延迟效果 new_end = time.time() print("运行时长:%.4f 秒" % (new_end-start)) return f return wrapper @runtime(1.5) def func_a(a): '''func_a --> hello''' print("hello"+a) time.sleep(0.5) return True @runtime() def func_b(b, c="xx"): '''func_b --> world''' print("world"+b+c) time.sleep(0.8) return True if __name__ == '__main__': func_a("a") print(func_a.__name__) print(func_a.__doc__)

运行结果

running function : func_a docstring: func_a --> hello helloa 运行时长:0.7522 秒 func_a func_a --> hello

2019年《python3自动化UI+接口》课程5月25-7月27开课主讲老师:上海-悠悠上课方式:QQ群视频在线教学上课时间:每周六、周日晚上20:30-22:30报名费:2000

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
python装饰器示例
python学习之装饰器
从零开始学Python:21课-函数的高级应用
Python装饰器和符号@ | Hom
理解 Python 装饰器看这一篇就够了 – 码农网
【连载电子书五】Python函数编程(下)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服