前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python笔记36-装饰器之wraps

python笔记36-装饰器之wraps

作者头像
上海-悠悠
发布2019-05-14 14:41:43
4470
发布2019-05-14 14:41:43
举报

前言

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

name和doc

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

代码语言:javascript
复制
import timedef func_a(a):
'''func_a --> hello'''
print("hello"+a)
time.sleep(0.5)
return Truedef func_b(b, c="xx"):
'''func_b --> world'''
print("world"+b+c)
time.sleep(0.8)
return Trueif __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内容

代码语言:javascript
复制
import timedef 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 Trueif __name__ == '__main__':
func_a("a")
print(func_a.__name__)
print(func_a.__doc__)

运行结果

代码语言:javascript
复制
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的装饰器来消除这样的副作用。

代码语言:javascript
复制
import time
from functools import wrapsdef 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)即可解决

运行结果

代码语言:javascript
复制
running function : func_a
docstring: func_a --> hello
helloa
运行时长:0.5004 秒
func_a
func_a --> hello

类装饰器

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

代码语言:javascript
复制
import time
from functools import wrapsclass runtime(object):
'''runtime class decorators'''
def __init__(self, slowly=1):
self.slowly = slowlydef __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 Trueif __name__ == '__main__':
func_a("a")
print(func_a.__name__)
print(func_a.__doc__)

运行结果

代码语言:javascript
复制
running function : func_a
docstring: func_a --> hello
helloa
运行时长:0.7522 秒
func_a
func_a --> hello
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 从零开始学自动化测试 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • name和doc
  • 装饰器加函数名称日志
  • functools
  • 类装饰器
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档