1、装饰器的作用及开放封闭原则
1、装饰器的作用:在不修改函数的调用方法,但是还想在原来的函数前后添加功能
2、开放封闭原则的具体含义:对扩展开放、对修改封闭
2、装饰器的一般语法:
首先,先看一个实例:计算某个函数的运行时间
import time
def timer(f): #step one
def inner(): #step four
start = time.time() #step six
time.sleep(0.01) #step seven
ret = f() #step eight
end = time.time() #step nine
print(end - start) #step ten
return ret #step eleven
return inner
f = timer(f) #得到的结果是inner
ret = f() #相当于调用inner函数,即inner()
该实例还可优化,python中有一种叫语法糖的东西,可以简化代码,简化之后的代码如下:
import time
def timer(f): #step one
@wraps(f) #语法糖,指明该装饰器修饰的是f,即timer的形参
def inner(): #step four
start = time.time() #step six
time.sleep(0.01) #step seven
ret = f() #step eight
end = time.time() #step nine
print(end - start) #step ten
return ret #step eleven
return inner
@timer #这个等价于:f = timer(f)
def f():
return "HelloWorld!"
ret = f() #这里直接调用即可,而不需要上面“f = timer(f)”这一步
上面将的都是单个装饰器修改一个函数,下面的这个实例将的是多个装饰器修饰一个函数时其执行顺序。
def wrapper1(func):#本例中func=inner2 #step one
def inner1(*args,**kwargs): #step seven
print('wrapper1,before func')#step eleven
ret = func() #step twelve 此时func = inner2,故此相当于ret = inner2()
print('wrapper1,after,func') #step seventeen
return ret #step nineteen inner1()执行完毕,返回结果
return inner1 #step eight
def wrapper2(func):#本例中func = f #step two
def inner2(*args,**kwargs):#step four
print('wrapper2,before,func')#step thirteen
ret = func(*args,**kwargs) #step fourteen 此时,func = f,故此相当于ret = f()
print('wrapper2,after,func') #step fifteen
return ret #step sixteen inner2()执行完毕,返回结果
return inner2#step five
@wrapper1#f = wrapper1(f)=inner1 #step six wrapper(f)中f=inner2;f = inner1
@wrapper2#f = wrapper2(f)=inner2 #step three f = inner2
def f(): #step nine
print('函数本体正在执行')
f()#inner1 #step ten 相当于:inner1()
其结果为:
wrapper1,before func
wrapper2,before,func
函数本体正在执行
wrapper2,after,func
wrapper1,after,func
从中可以得出当多个装饰器修饰一个函数时,其执行顺序是:先执行上面装饰器(@wrapper1
)的前面的语句,在执行下面装饰器(@wrapper2
)前面的语句,然后执行被修饰的函数(f
),最后依次执行下面的和上面的函数之后的语句。
总结: 一般装饰器的固定格式如下:
def 装饰器名(被装饰的函数):#装饰器英文名'wrapper'
def 函数名(*args,**kwargs):#定义一个新的内部函数,用来执行被装饰的函数
此处编写被装饰函数被执行前需要执行的代码
结果 = 被装饰的函数()
此处编写被装饰函数被执行之后需要执行的代码
return 结果
return 函数名
@装饰器名
def 被装饰函数(参数):
函数体