定义:装饰器本质上就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。
应用场景:比如插入日志、性能测试、事务处理、缓存、权限校验等场景。
一、装饰器的形成过程
1、自定义装饰器
#简单装饰器 import time def timmer(f): def inner(): start_time = time.time() time.sleep(0.1) f() end_time = time.time() print('----> 执行效率:%s' %(end_time - start_time)) return inner #需要引用装饰器的函数 def func(): print('嘻嘻更健康') #引用装饰器 func = timmer(func) #inner func() #inner() #输出结果 嘻嘻更健康 ----> 执行效率:0.10022902488708496
2、装饰器的语法糖
#装饰的语法糖@ def timmer(f): #装饰器 def inner(): f() return inner @timmer #@timmer 相当于 func = timmer(func) def func(): #要引用装器的函数 print('嘻嘻更健康') func() #func() = inner() 调用装饰器 #输出结果 嘻嘻更健康
3、带参数函数的装饰器
# 函数带参数的装饰器 def timmer(f): #此处传入动态参数 def inner(*args,**kwargs): f(*args,**kwargs) return inner @timmer # func = timmer(func) def func(a): # 第一个函数,参数a print('%s嘻嘻更健康'%a) @timmer # func1 = timmer(func1) def func1(a,b): # 第二个函数,参数a、b print('%s和%s嘻嘻更健康' %(a,b)) func('张三') func1('张三','李四') #输出结果 张三嘻嘻更健康 张三和李四嘻嘻更健康
4、带返回值函数的装饰器
# 函数带有返回值的装饰器 def timmer(f): def inner(*args,**kwargs): ret = f(*args,**kwargs) return ret # 将函数的返回值返回 return inner @timmer # func = timmer(func) def func(): return '函数的返回值' #执行函数 print(func()) #输出结果 函数的返回值
5、带参数的装饰器
#带参数的装饰器 flag = True def outer(flag): def timer(func): def inner(*args,**kwargs): if flag==True: print('''执行函数之前要做的''') ret = func(*args,**kwargs) if flag==False: print('''执行函数之后要做的''') return ret return inner return timer @outer(flag) def func(): print('这是执行函数') #调用执行函数 func() #输出结果 执行函数之前要做的 这是执行函数
6、函数带有多个装饰器
#装饰器1 def wrapper1(func): def inner(): print('wrapper1, before func') func() print('wrapper1, after func') return inner #装饰器2 def wrapper2(func): def inner(): print('wrapper2, before func') func() print('wrapper2, after func') return inner @wrapper2 @wrapper1 def func(): print('执行函数') func() #输出结果 wrapper2 ,before func wrapper1 ,before func 执行函数 wrapper1 ,after func wrapper2 ,after func
7、查看函数信息的相关方法
#正常情况下查看 def index(): '''函数的注释''' print('from index') print(index.__doc__) #查看函数注释的方法 print(index.__name__) #查看函数名的方法 #输出结果 函数的注释 index
#查看带有装饰器的函数 from functools import wraps def decorate(func): @wraps(func) #加在最内层函数正上方 def wrapper(*args,**kwargs): return func(*args,**kwargs) return wrapper @decorate def index(): '''函数的注释''' print('from index') print(index.__doc__) print(index.__name__) #输出结果 函数的注释 index
总结:通用装饰器公式
#固定公式1 def wrapper(func): def inner(*args,**kwargs): '''执行函数之前要做的''' ret = func(*args,**kwargs) '''执行函数之后要做的''' return ret return inner #固定公式2 from functools import wraps def deco(func): @wraps(func) #加在最内层函数正上方 def wrapper(*args,**kwargs): return func(*args,**kwargs) return wrapper @wrapper def func1(): print("函数func1") func1() #函数func1 @deco def func2(): print("函数func2") func2() #函数func2
二、装饰器的开放封闭原则
1、对扩展是开放的
为什么要对扩展开放呢?
我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。
2、对修改是封闭的
为什么要对修改封闭呢?
就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。