专栏首页从零开始学自动化测试python笔记36-装饰器之wraps

python笔记36-装饰器之wraps

前言

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

name和doc

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

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内容

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__)

运行结果

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 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)即可解决

运行结果

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

类装饰器

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

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__)

运行结果

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

本文分享自微信公众号 - 从零开始学自动化测试(yoyoketang),作者:上海悠悠

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-05-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • python笔记35-装饰器

    python装饰器本质上就是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰器的返回值也是一个函数对象。 很多python初学者学到...

    上海-悠悠
  • Linux学习23-Xftp上传文件显示乱码问题

    当我们在windows新建一个文件,里面有中文时,使用Xftp上传到linux服务器上,会出现乱码问题。

    上海-悠悠
  • selenium+python自动化97--unittest参数化(paramunittest)

    前言 paramunittest是unittest实现参数化的一个专门的模块,可以传入多组参数,自动生成多个用例 前面讲数据驱动的时候,用ddt可以解决多组数据...

    上海-悠悠
  • golang 日志模块(log)

    copy_left
  • 函数对象

    py3study
  • Python闭包装饰器使用方法汇总

    对全局函数进行修改:在函数当中加global,在闭包中外边中的变量加nonlocal

    砸漏
  • 小朋友学Python(27):全局变量的引用和修改

    一、引用 例1 a = 1 def func(): if 1 == a: print("a = %d" % a) if __name__...

    海天一树
  • 73-递归函数计算阶乘

    凯茜的老爸
  • go语言的匿名函数

    1-声明一个匿名函数 func(参数列表) 返回值列表 { 函数体… } 2-匿名函数的调用

    李海彬
  • 可怕的extern关键字一、不利之处二、例子三、分析四、正确做法

    如果函数原型改变的话,每个extern声明的地方都要改一遍。 如果有地方没改到呢? 我们通过一个例子来看下悲剧是怎么发生的。

    coderhuo

扫码关注云+社区

领取腾讯云代金券