装饰器本身既可以是函数也可以是类,装饰的对象同样可以是函数也可以是类。
例1:
import time
class Timer:
def __init__(self,func) -> None:
self.func = func
def __call__(self, *args, **kwargs):
start = time.time()
ret = self.func(*args, **kwargs)
print(f'Time:{time.time()-start}')
return ret
@Timer
def add(a,b):
time.sleep(1)
return a+b
print(add(2,3))
输出结果:
@Timer
def add(a,b):
time.sleep(1)
return a+b
等价于:
add = Timer(add)
这个装饰器,相当于把一个装饰器变成了一个Timer类的对象,然后add被传入进了__init__中,保存为self.func,在后面调用add(2,3)的时候,实际上相当于调用了__call__这个函数,做了一个对象的调用,后面参数2和3就被传入到了__call__里面,然后依顺序运行了代码。
例2,带参数的类装饰器:
import time
class Timer:
def __init__(self,prefix) -> None:
self.prefix = prefix
def __call__(self, func):
def wrapper(*args,**kwargs):
start = time.time()
ret = func(*args, **kwargs)
print(f'{self.prefix}:{time.time()-start}')
return ret
return wrapper
@Timer(prefix = 'curr_time:')
def add(a,b):
time.sleep(1)
return a+b
# 等价于: add = Timer(prefix = 'curr_time:')(add)
print(add(2,3))
输出结果:
可以看到,我们相当于先实例化了一个Timer对象,然后把add作为一个参数传入这个实例化的Timer对象,再把调用的返回值保存到add里。
这种写法有点类似于函数装饰器。