什么是装饰器
一个装饰器就是一个函数,它接受一个函数作为参数并返回一个新的函数,简单的来说就是给一个函数增加额外的操作,并且可以复用。好处是 不直接入侵原有的代码逻辑,
装饰器的用途
实现一个函数运行装饰器
import time
from functools import wraps
def decorator(func):
@wraps(func) # 如果对函数元信息没有要求可以不添加
def do(*args, **kwargs):
start_tm = time.time()
func()
end_tm = time.time()
print(f"函数运行时间{end_tm - start_tm}")
return do
def 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 do
return decorator
@timeit('函数运行时间为:%.2fs --来自带参数的装饰器')
def func():
time.sleep(1)
pass
if __name__ == '__main__':
func()
类装饰器
实现类 装饰器 主要是在类中实现call 函数,否者调用不起来
class Timeit:
def __init__(self, fun):
self.fun = fun
def __call__(self, *args, **kwargs):
start_time = time.time()
self.fun()
end_tm = time.time()
print(end_tm - start_time)
@Timeit
def func():
time.sleep(1)
pass
if __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] = num
else:
num = cache_dict[n]
return num
return do
@cache
def fib(n):
a, b = 0, 1
while n > 0:
a, b = b, a + b
n -= 1
yield a
import time
class TiemTrace:
def __init__(self, f):
self.f = f
print(f.__doc__)
def __now(self):
return time.time()
def __enter__(self):
self.start = self.__now()
return self
def __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 val
if __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。装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,装饰器的作用就是为已经存在的对象添加额外的功能。