什么是装饰器
一个装饰器就是一个函数,它接受一个函数作为参数并返回一个新的函数,简单的来说就是给一个函数增加额外的操作,并且可以复用。好处是 不直接入侵原有的代码逻辑,
装饰器的用途
实现一个函数运行装饰器
import timefrom functools import wrapsdef decorator(func):@wraps(func) # 如果对函数元信息没有要求可以不添加def do(*args, **kwargs):start_tm = time.time()func()end_tm = time.time()print(f"函数运行时间{end_tm - start_tm}")return dodef timeit(out='函数运行时间为:%.2fs'):def decorator(func):def do(*args, **kwargs):start_time = time.time()func()end_tm = time.time()print(out % (end_tm - start_time))return doreturn decorator@timeit('函数运行时间为:%.2fs --来自带参数的装饰器')def func():time.sleep(1)passif __name__ == '__main__':func()
类装饰器
实现类 装饰器 主要是在类中实现call 函数,否者调用不起来
class Timeit:def __init__(self, fun):self.fun = fundef __call__(self, *args, **kwargs):start_time = time.time()self.fun()end_tm = time.time()print(end_tm - start_time)@Timeitdef func():time.sleep(1)passif __name__ == '__main__':func()
总结:
- 装饰器是在运行的时候就加载的
- 多个装饰器 自上而下的启动【拨洋葱一样】
- 使用装饰器为了保持函数的元信息不被覆盖 通常使用wraps来装饰保留原信息
- 装饰器中有闭包的身影
实现一个缓存装饰器
# 实现fib 装饰器缓存版本# 实现对 fib(n) 字典的 缓存计划# 自己实现的 装饰器 执行二次的确节约了时间,但是 如何做 第一次就进行cache?cache_dict = {}def cache(fun):def do(*args, **kwargs):n = args[0]if not n in cache_dict:num = fun(n)cache_dict[n] = numelse:num = cache_dict[n]return numreturn do@cachedef fib(n):a, b = 0, 1while n > 0:a, b = b, a + bn -= 1yield aimport timeclass TiemTrace:def __init__(self, f):self.f = fprint(f.__doc__)def __now(self):return time.time()def __enter__(self):self.start = self.__now()return selfdef __exit__(self, exc_type, exc_val, tb):self.end = self.__now()print('cost {}'.format(self.end - self.start))def __call__(self, n):start = self.__now()val = self.f(n)end = self.__now()print('{}, {}, {}, cost: {} seconds'.format(self.f.__name__, n , val, (end - start)))return valif __name__ == '__main__':start_tm = time.time()for i in fib(10):print(i)end_tm = time.time()print(end_tm - start_tm)start_tm = time.time()for i in fib(10):print(i)end_tm = time.time()print(end_tm - start_tm)with TiemTrace(fib) as f:for i in f(10):print(i)
AOP概念及作用
AOP 即面向切面编程,指扩展功能不修改源代码,将功能代码从业务逻辑代码中分离出来。
主要作用就是将类似于日志记录,性能统计,安全控制,事务处理,异常处理等重复性的代码块从业务逻辑代码中划分出来,对这些行为的分离。并且将它们独立到非知道业务逻辑的方法中,从而做到改变这些行为的时候不影响业务逻辑代码。
装饰器实现AOP
我们python中使用装饰器实现AOP。装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,装饰器的作用就是为已经存在的对象添加额外的功能。
