使用实例:
背景:测试过程中,遇到这样一种情况,A接口请求后需要等待几秒再执行B接口请求,可以给B加个装饰器实现此功能,让B每次请求时先等待几秒。
example1:
import time def wait(func): # func(*args, **kw)可以使函数适配任意多的参数 def wrapper(*args, **kw): time.sleep(3) return func(*args, **kw) return wrapper
class Template: @wait def get_opt_auditresult(self, engineid, type): # time.sleep(4) @wait实现了该功能 url = '' if type == 1: url = self.conf.get('auditcenter', 'address') + '/api/v1/opt/all /auditResultList/' + str(engineid) return self.get(url) # 调用 from common.template_2_x import Template from config.read_config import ReadConfig import unittest import warnings class TestDelete(unittest.TestCase): def setUp(self): warnings.simplefilter("ignore", ResourceWarning) self.tem = Template() def test_opt_07(self): '''审核通过,医生修改处方''' engineid = self.tem.get_opt_engineid('opt','处方一',1) # 审核打回 self.tem.opt_audit(engineid,0) self.tem.send_data('opt','修改处方一1',**self.tem.change_data) # 只修改处方头 res = self.tem.get_opt_auditresult(engineid,1) self.assertEqual(2,res['data'][0]['rejectStatus']) if __name__ == '__main__': unittest.main()
实例代码地址:传送门
example2:
def dec(f): n = 3 def wrapper(*args,**kw): return f(*args,**kw) * n return wrapper @dec def foo(n): return n * 2 foo(2) 相当于: def dec(f): n = 3 def wrapper(*args,**kw): return f(*args,**kw) * n return wrapper def foo(n): return n * 2 foo=dec(foo) foo(2)
简言之,foo(2)=wrapper(2)=foo(2)*3=2*2*3=12
装饰器理论介绍
装饰器是什么:
装饰器是为已经存在的函数或者对象添加额外的功能。本质上是一个闭包函数(闭包函数:本质是个嵌套函数,内层函数引用外层函数的变量,外层函数返回内层函数)
装饰器的作用:
1.不修改已有函数的源代码
2.不修改已有函数的调用方式
3.为已有函数添加额外的功能
格式一:有参数
@decorator(arg1, arg2) def fun(): pass 等价于: def fun(): pass fun = decorator(arg1, arg2)(fun)
格式二:无参数
import time
from functools import wraps
def timethis(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(func.__name__, end - start)
return result
return wrapper
@timethis
def conutdown(n):
while n > 0:
n -= 1
"""
@timethis
def conutdown(n):
while n > 0:
n -= 1
等价于 conutdown = timethis(conutdown) 该装饰器代码本身就会运行,而不是等到conutdown(10000)才执行,理解不了的话,在@timethis处打个断点debug一下就知道怎么执行的了
执行过程为:
调用timethis,返回wrapper,且conutdown指向wrapper,所以后面执行conutdown(10000)就相当与执行wrapper(10000)
"""
conutdown(10000)
print(conutdown.__name__)
输出结果为:
conutdown 0.015621423721313477
conutdown # 注意红色字体@wraps(fun1)是为了避免被装饰函数自身的信息丢失,如果注释@wraps(fun1),该输出结果将会是wrapper,故任何时候定义装饰器的时候,都应该使用 functools 库中的 @wraps 装饰器来注解底层包装函数
格式三:有多个装饰器
@decotator_one @decorator_two def fun(): pass 等价于: def fun(): pass fun = decorator_one(decorator_two(fun)
三大内置装饰器(@staticmethod、@classmethod、@property)
静态方法:是类中的方法,不需要实例。 需要通过修饰器 @staticmethod 来进⾏修饰,静态⽅法不需要多定义参数
- 特性:静态方法不能使用类变量和实例变量
- 调用方式:一般通过类名调用
类方法:是类对象所拥有的⽅法,需要⽤修饰器 @classmethod 来标识其为类⽅法,对于类⽅法,第⼀个参数必须是类对象,⼀般以 cls 作为第⼀个参数(当然可以⽤其他名称的变量作为其第⼀个参数,但是⼤部分⼈都习惯以'cls'作为第⼀个参数的名字,就最好⽤'cls'了),能够通过实例对象和类对象去访问
- 特性:只能访问类变量,不能访问实例变量
- 调用方式:通过实例对象或类对象去访问