一、软件的设计原则
#软件的设计要遵循"封闭开放"原则,即对于修改是封闭的,对于扩展是开放的。对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。对修改封闭,意味着对象一旦设计完成,就可以独立完成其工作,而不要对其进行修改。
这就为装饰的产生,提供了支撑
二、装饰器
1、什么是装饰器
’装饰’代指为被装饰对象添加新的功能,’器’代指器具/工具,装饰器与被装饰的对象均可以是任意可调用对象。概括地讲,装饰器的作用就是在不修改被装饰对象源代码和调用方式的前提下为被装饰对象添加额外的功能。
装饰器的应用场景:
# 插入日志 # 性能测试 # 事务处理 # 缓存 # 权限校验 等等
二、装饰器的实现
2.1无参装饰器的实现
# 需求:在不修改index函数的源代码以及调用方式的前提下为其添加统计运行时间的功能 ''' import time def index(x,y): time.sleep(3) print('index %s, %s' % (x,y)) index(111,222) ''' # 解决方案一:失败 # 问题:没有修改被装饰对象的调用方式,但是修改了其源代码 import time def index(x,y): start=time.time() time.sleep(3) print('index %s %s' %(x,y)) stop = time.time() print(stop - start) index(111,222) # 解决方案二: # 问题:没有修改被装饰对象的调用方式,也没有修改了其源代码,并且加上了新功能 # 但是代码冗余 import time def index(x,y): time.sleep(3) print('index %s %s' %(x,y)) start=time.time() index(111,222) stop=time.time() print(stop - start) start=time.time() index(111,222) stop=time.time() print(stop - start) # 解决方案三: # 问题:解决了方案二代码冗余问题,但带来一个新问题即函数的调用方式改变了 import time def index(x,y): time.sleep(3) print('index %s %s' %(x,y)) def wrapper(): start=time.time() index(111,222) stop=time.time() print(stop - start) wrapper() # 方案三的优化 import time def index(x,y): time.sleep(3) print('index %s %s' %(x,y)) def wrapper(*args,**kwargs): start=time.time() index(*args,**kwargs) stop=time.time() print(stop - start) wrapper(111,222) # 解决方案四 # 问题:解决了方案三函数的调用方式改变问题,但带来一个新问题即被装饰对象有返回值时返回值为None import time def run_time(func): def wrapper(*args, **kwargs): start = time.time() func(*args, **kwargs) stop = time.time() print(stop-start) return wrapper def index(x,y): time.sleep(1) print('index %s,%s' % (x,y)) return 123 res = index(111, 222) print(res) # 方案四优化(装饰器终极版):给func用res来接收返回值然后return res,来实现对被装饰函数返回值的接收 import time def run_time(func): def wrapper(*args, **kwargs): start = time.time() res = func(*args, **kwargs) stop = time.time() print(stop-start) return res return wrapper def index(x,y): time.sleep(1) print('index %s,%s' % (x,y)) return 123 index = run_time(index) res = index(111, 222) print(res)
2.2语法糖的使用
import time def run_time(func): def wrapper(*args, **kwargs): start = time.time() res = func(*args, **kwargs) stop = time.time() print(stop-start) return res return wrapper # 在被装饰对象正上方的单独一行写@装饰器名字 @run_time # index = run_time(index) def index(x,y): time.sleep(1) print('index %s,%s' % (x,y)) return 123 res = index(111, 222) print(res)
2.3有参装饰器的实现
。。。
2.4小节
# 无参装饰器模板 def outter(func): def wrapper(*args,**kwargs): # 1、调用原函数 # 2、为其增加新功能 res=func(*args,**kwargs) return res return wrapper def index(): print('form index') index() # 有参装饰器模板