不带参数的装饰器 from functools import wraps # 封装函数进行装饰,保留被装饰函数属性def zsq(sc): # 设计一个装饰器函数,传入被装饰函数 @wraps(
不带参数的装饰器
from functools import wraps # 封装函数进行装饰,保留被装饰函数属性def zsq(sc): # 设计一个装饰器函数,传入被装饰函数 @wraps(sc) def nsc(*args, **kwargs): # 设计它的封装 jg = sc(*args, **kwargs) # 调用被装饰函数,配合百搭 print('nsc function.') print(jg) return 0 return nsc@zsqdef zzsc(): # 设计最终函数,也当做sc被装饰,这里百搭参数 '''zzsc...''' print('sc function.') return 1 # 返回值# 定义过程:# 设计zzsc为被装饰函数,并作为输入函数参数被传入装饰器# 装饰器封装一个函数,并传入百搭参数# 装饰器返回封装函数,并把最终函数指向封装函数,# 这时候最终函数的参数(百搭参数)#执行过程:# 调用最终函数,传入百搭参数# 执行封装函数。。# 执行被装饰函数#PS:# 装饰器的返回值肯定是封装函数# 最终函数|被装饰函数的返回值,用于供封装函数可能使用# 封装函数的返回值会成为最终函数的返回值被返回
装饰器的本质是函数,接收一个函数作为参数,并且返回一个函数
装饰器通常会返回一个封装函数,这个封装函数在传入的函数前后做一些修饰
装饰器肯定是高阶函数
带参数的装饰器
import timefrom functools import wrapsdef timeit(cpu_time=False): time_func = time.clock if cpu_time else time.time def dec(fn): @wraps(fn) def wrap(*args, **kwargs): start = time_func() ret = fn(*args, **kwargs) print(time_func() - start) return ret return wrap return dec
@timeit()def fun(n): time.sleep(n) return nfun(3)
@timeit(True)def fun(n): time.sleep(n) return nfun(3)
带参数的装饰器是一个函数,返回一个装饰器
带参数的装饰器多了一层
装饰器的应用
cache
from functools import wrapsimport timeclass DictCache: # 缓存 def __init__(self): self.cache = dict() def get(self, key): return self.cache.get(key) def set(self, key, value): self.cache[key] = valuedef cache(instance): # 缓存装饰器 def dec(fn): @wraps(fn) def wrap(*args, **kwargs): pos = ','.join((str(x) for x in args)) kw = ','.join('{}={}'.format(k, v) for k, v in sorted(kwargs.items())) key = '{}::{}::{}'.format(fn.__name__, pos, kw) # 拼装key,第一次存入缓存 ret = instance.get(key) if ret is not None: # 检查缓存是否已有 return ret ret = fn(*args, **kwargs) # 未缓存,执行 instance.set(key, ret) return ret return wrap return deccache_instance = DictCache()@cache(cache_instance)def long_time_fun(x): time.sleep(x) return xlong_time_fun(3)
第二次long_time_fun不会执行
标准库已实现
from functools import lru_cacheimport time@lru_cache()def long_time_fun(x): time.sleep(x) return xlong_time_fun(3)
监控
from functools import wrapsimport loggingclass LoggingMetric: def send(self, key, value): longging.warning('{} => {}'.format(key, value))def mertic(prefix, instance): def timeit(fn): @wraps(fn) def wrap(*args, **kwargs): start = time.time() ret = fn(*args, **kwargs) key = '{}.{}.{}'.format(prefix, fn.__module__, fn.__name__) print(key) return ret return wrap return timeit@mertic(prefix='chalotte', instance=LoggingMetric())def long_time_fun(x): time.sleep(x) return xlong_time_fun(1)
身法验证 授权
from functools import wrapsdef do_auth(info): # 通过header里的身份信息验证用户身份 return Truedef auth(header_name): def dec(fn): @wraps(fn) def wrap(request): info = request.headers.get(header_name) if do_auth(info): return fn(request) return AccessDenied() return wrap return dec@auto('X-Auth-Info')def handle(request): pass# 设定
路由
github.com/pallets/flask/blob/master/flask/app.py