2020-06-18 目录:
一、装饰器
1.1 什么是装饰器
1.2 为何要用装饰器
1.3 怎么用装饰器
二、语法糖
三、装饰器的模板
3.1 模板
3.2 wraps+ 终极模板
一、装饰器
1.1 什么是装饰器
名词解释: 器:即功能/工具 装饰:为被装饰的对象添加额外的功能
1.2 为何要用装饰器
程序开发需要遵循开放封闭原则:即对拓展功能开放,对修改源代码封闭 装饰器:可以在不修改被装饰对象的源代码及其调用方式的前提下,为被装饰对象添加新功能的工具
1.3 怎么用装饰器
比如:为两个简单的打印函数添加程序运行时间测试的功能
import time def index(x, y): # 原始index函数 print(x, y, 'from index') time.sleep(1) return 111 def name(x): # 原始name函数 print('name:%s' % x) time.sleep(0.5) return 222 def outer(func): # 闭包函数 为wrapper函数传值(函数名) def wrapper(*args, **kwargs): # 装饰函数,不同函数调用可以接受不同个数、格式的值 start_time = time.time() # 添加新功能 res = func(*args, **kwargs) # 调用outer传入的func函数,将wrapper汇总的参数打散成原形传进func,并将返回值赋值给res end_time = time.time() print('running time is %s' % (end_time - start_time)) return res # 同于传递原始func函数的返回值 return wrapper # 一定不能加括号 index = outer(index) # index=wrapper 将wrapper装饰过的函数重新绑定给函数名index (不想使用装饰器时删除此行即可) res1 = index(1, 2) print(res1) name = outer(name) # name = wrapper(同理,不想使用装饰器时删除此行即可) res2 = name('jason') print(res2) """
运行结果:>>> 1 2 from index running time is 1.000702142715454 111 name:jason running time is 0.5009057521820068 222 """
二、语法糖
@outer 写在被装饰函数定义之前单独一行(必须先定义装饰器outer) 可以替代上面代码里面的 index = outer(index) 和 name = outer(name)
用来使函数调用时尽量与原函数没有操作上的不同
同样的,不想使用装饰器功能时删除此行就行
三、装饰器的模板
3.1 模板
装饰器的设计即可基于如下模板进行修改、添加需要的功能:
def outer(func): def wrapper(*args, **kwargs): res = func(*args, **kwargs) return res return wrapper
3.2 wraps+终极模板
使用方法:写在最内层函数正上方
作用:将被装饰函数的种种属性都赋值给新函数,使得装饰过的函数看起来“没有被动过手脚”
于是就有了最完整的终极模板:
from functools import wraps def outer(func): @wraps() # 写在最内层函数的正上方 def wrapper(*args, **kwargs): res = func(*args, **kwargs) return res return wrapper