装饰器
python中的函数如果不添加()进行操作,会将自己的内存地址返回.装饰器就主要是利用这种原理进行工作.
实验一
原有代码如下,
def Calc(a, b):
if a > b:
print("当a大于b")
print("干a大于b的其它事情")
elif a < b:
print("当a小于b")
print("干a小于b的其它事情")
else:
print("a等于b")
现需求如下,要求在不改变Calc函数代码和调用方式的情况下,增加对用户使用这个Calc进行一个int类型检查的功能
def inspect_Num(Orig_func):
def wrapper(a, b): #wrapper函数会接收Calc()执行时获得的参数
a = int(a)
b = int(b) #这里没有做字符和数字,符号的检查.主要是演示装饰器功能,代码太多容易看蒙圈
return Orig_func(a, b)
#才真正的执行Calc函数.
return wrapper
@inspect_Num
#在这里@inspect_Num相当于Calc=inspect_Num(Calc),将CLac函数的内存地址当参数执行inspect_Num函数
def Calc(a, b):
if a > b:
print("当a大于b")
print("干a大于b的其它事情")
elif a < b:
print("当a小于b")
print("干a小于b的其它事情")
else:
print("a等于b")
Calc(7,5)
#此时执行Calc函数实际上是将Calc当参数给inspect_Num,并将7,5作为参数传入了login_Fun函数内
- 执行流程
- 将inspect_Num函数载入内存
- 读取 @inspect_Num 装饰器标记
- 执行inspect_Num函数 (因为 @inspect_Num相当于: Calc=inspect_Num(Calc))
- 此时inspect_Num函数将载入wrapper函数内存地址并作为返回值返回)
- 装饰器标记完毕
- 将Calc函数载入内存
- 执行Calc() 因为第三步的封装此时的Calc()其实是执行的wrapper()并传入参数
- 触发装饰器标记wrapper函数
- 将Calc函数内存地址作为参数传入内部
- 将Calc的参数7和5传入wrapper内部
- wrapper内部执行代码执行(由于wraper函数里有return Orig_func)
- 由于wraper函数里有return Orig_func() 找到真正Calc()
- 最后返回执行的Calc函数执行结果,
实验二
要求在不改变Calc函数代码和调用方式的情况下,增加对功能:1,用户使用Calc前int类型检查的功能,2,在最后输出一个a和b相加的结果
def inspect_Num(a, b): #新增功能1,检查数据
a = int(a)
b = int(b)
print("Num检查")
return a, b
def add_Num(a, b): #新增功能2,加法运算
i = a + b
print("a + b = %s"% i )
return i
def modify_Func(first_func, second_func): #传入需要增加的功能函数
def tran_Func(calc_func): #传入主函数
def wrapper(a, b): #装饰器函数,按照条件执行新的功能函数
first_func(a, b) #执行calc前的功能
calc_func(a, b) #执行calc主函数
second_func(a, b) #执行calc后的功能函数
return wrapper
return tran_Func
@modify_Func(inspect_Num, add_Num)
def Calc(a, b):
if a > b:
print("当a大于b")
print("干a大于b的其它事情")
elif a < b:
print("当a小于b")
print("干a小于b的其它事情")
else:
print("a等于b")
Calc("8","9")
- 总体思路和实验一查不多.通过代码调试可以清晰的看到程序运行的路线.
- 实验代码并不严谨,只是为了演示作为函数运行的占位标识