一、不带参数的装饰器
1、案例1
class Demo:
pass
@Demo
def work():
print('work开始工作')
if __name__ == '__main__':
work()
def work():
TypeError: Demo() takes no arguments
第4、5行的代码的执行逻辑是:work=Demo(work)
相当于初始化一个实例对象,需要定义参数去接收work,案例2
2、案例2
class Demo:
def __init__(self,func):
self.func=func
@Demo
def work():
print('work开始工作')
if __name__ == '__main__':
work()
work()
TypeError: ‘Demo’ object is not callable
实例化对象,不能调用,如果想要调用需要使用__call__()方法
3、案例3
class Demo:
def __init__(self,func):
self.func=func
def __call__(self, *args, **kwargs):
self.func()
@Demo
def work():
print('work开始工作')
if __name__ == '__main__':
work()
work开始工作
二、带参数的装饰器
方法1:采用闭包
class Demo:
def __init__(self,number):
self.number=number
def __call__(self,func, *args, **kwargs):
def wrapper(*args,**kwargs):
print('拓展功能1')
res=func(*args,**kwargs)
print('拓展功能2')
return res
return wrapper
@Demo(number=24)
def work(a,b):
return a+b
if __name__ == '__main__':
print(work(1,2))
拓展功能1
拓展功能2
3
方法二:不采用闭包
class Demo:
def __init__(self,number):
self.number=number
def __call__(self, func):
self.func=func
return self.run
def run(self,*args,**kwargs):
print('拓展功能1')
res=self.func(*args,**kwargs)
print('拓展功能2')
return res
@Demo(number=12) #work=Demo(number=12)(work(a,b))
def work(a,b):
return a+b
if __name__ == '__main__':
print(work(11,22))
拓展功能1
拓展功能2
33
三、将多个装饰器封装到一个类里面
1、使用静态方法实现
class Mytest:
@staticmethod
def test1(func):
def wrapper(*args,**kwargs):
print('拓展功能1')
res=func(*args,**kwargs)
print('拓展功能2')
return res
return wrapper
@staticmethod
def test2(func):
def wrapper(*args,**kwargs):
print('拓展功能1')
res=func(*args,**kwargs)
print('拓展功能2')
return res
return wrapper
@Mytest.test1
def work1(a,b):
return a+b
@Mytest.test2
def work2(a,b):
return a-b
if __name__ == '__main__':
print(work1(24,8))
print(work2(24,8))
拓展功能1
拓展功能2
32
拓展功能1
拓展功能2
16
2、使用类方法实现
class Mytest:
@classmethod
def test1(cls,func):
def wrapper(*args,**kwargs):
print('拓展功能1')
res=func(*args,**kwargs)
print('拓展功能2')
return res
return wrapper
@classmethod
def test2(cls,func):
def wrapper(*args,**kwargs):
print('拓展功能1')
res=func(*args,**kwargs)
print('拓展功能2')
return res
return wrapper
@Mytest.test1
def work1(a,b):
return a+b
@Mytest.test2
def work2(a,b):
return a-b
if __name__ == '__main__':
print(work1(24,8))
print(work2(24,8))
四、多个装饰器同时装饰一个函数的执行顺序
test_datas = [{"title": "测试用例", "data": "data1", "res": 1}]
@ddt
class TestDemo:
@unpack test_demo=unpack(data(*test_datas)(test_demo))
@data(*test_datas) test_demo=data(*test_datas)(test_demo)
def test_demo(self, item):
print('执行测试用例')
执行顺序:
test_demo=unpack(data(*test_datas)(test_demo))