装饰器
-
定义:装饰器其实就是一个以函数作为参数并返回一个替换函数的可执行函数,即装饰器是一个函数,它以函数作为参数,返回另一个函数。
-
实例
函数装饰器:若需要定制相关参数,可以再装饰器外再套一层装饰器
def wrapper(func):
def decorator(*args, **kwargs):
# do something for func
res = func(*args, **kwargs)
# do something for func
return res
retrun declare
newfun = wrapper(fun)
newfun(*arg, **kwarg)
# 或者
@wrapper
fun
类装饰:采用类装饰后,函数将作为类的函数来使用
class wrapper:
def __init__(self, func):
self.func = func
def __call__(self, *arg, **kwargs):
# do something for func
res = self.func(*args, **kwargs)
# do something for func
return res
@wrapper
fun(*arg, **kwargs)
对象装饰
# 对比使用类作为装饰器,使用对象作为装饰器有些时候更有灵活性,例如能够方便定制和添加参数。此时函数是对象的函数
class wrapper:
def __init__(self, *wargs, **wkwargs):
self.arg = warg
self.kwarg = kwargs
def __call__(self,func):
def wrap(*args, **kwargs):
# do something for func
res = self.func(*args, **kwargs)
# do something for func
return wrap
@wrapper(wargs, wkwargs)
fun(*args, **kwargs)
常用的装饰器
# 超时装饰器
def timeout(seconds):
def decorator(func):
def _new_fun(old_fun, result, old_args, old_kwargs):
result.append(old_fun(*old_args, **old_kwargs))
@functools.wraps(func)
def wrapper(*args, **kw):
result = []
kwargs = {
"old_fun": func,
"result": result,
"old_args": args,
"old_kwargs": kw
}
t = threading.Thread(target=_new_fun, args=(), kwargs=kwargs, daemon=True)
t.start()
t.join(seconds)
if len(result) > 0:
return result[0]
else:
raise TimeoutException("运行时间超时", seconds)
return wrapper
return decorator
# 判断下列语句是否超时
# 统计用时
import time
import functools
def logtime(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
res = func(*args, **kwargs)
end = time.perf_counter()
print(f'函数 {func.__name__} 耗时 {(end - start) * 1000} ms')
return res
return wrapper
# 参数缓存
from functools import lru_cache