简述装饰器

作者:Dayle,转载请说明出处:https://www.cnblogs.com/dayle/p/10003844.html
 
装饰器:就是一个函数:
定义:装饰器实际上就是为了给某程序增添功能,但该程序已经上线或已经被使用,那么就不能大批量的修改源代码,这样是不科学的也是不现实的,因为就产生了装饰器,使得其满足:
1:不能修改源代码
2:不能修改调用方式
高阶函数:a:把一个函数名当作实参传给另一个函数
b:返回值中包含函数名
嵌套函数:一个函数中嵌套另一个函数
 
简单装饰器代码

 

 

以下,用行数代替每一行的内容,
首先,从上往下看,函数只有被调用的时候才会执行,所以执行的第一步就是语法糖@deco,他就在test函数的上方,那么,我们就可以得出实际上他的另一种写法就是 test = deco(test)(规定,不需要理解,就得这么记)
 
然后我们假设在执行这条命令: test = deco(test)。
相当于把test当作deco的实参传给了deco函数,那么我们看deco函数:第二行
 
deco函数是一个嵌套函数,那么我们一步步往下看,
第三行:里面还有一个函数,这个函数是wrapper函数,在形参的位置写了*args, **kwargs,这个代表传给函数的实参,那么就是‘aaa’,作用:为了防止工作中不止传入一个实参,而是很多个的时候,不需要在多次输入,直接调用所有实参。
第四行:我之前说过,一看到@deco,就是看到了test = deco(test),那么可以得出,deco函数里的形参的值就是test。而deco函数的形参为func,那么,间接的func=test,那么,这里的func(*args, **kwargs)这个语句也就是可以按我们的理解转换成为test('aaa'),那么这个语句就是在执行test函数,那么现在,就要找到test函数来执行:第9行。
 
第9行:执行test函数的结果就是:my name is aaa .
执行完之后回到原位置继续执行
第5行,打印‘添加新功能’
那么wrapper函数就执行完成了。跳出这一层函数,再来看他的外面一层函数体:deco函数,他有一个返回值,返回值为wrapper,那这个值其实就是wrapper函数的内存地址
 
然后看我注释的一行第12行。
我说过这其实就是@deco的原型。
那么这里将deco函数的返回值赋给了test,那么现在test已经不再是test了,而是wrapper,那么说,也就是wrapper函数的内存地址。test = wrapper
 
第13行,test('aaa'),其实就是在执行 wrapper('aaa')
那么结果如下:
 
原理:
现在返回头看我的装饰器的定义:
那么现在我的函数体没有改变,我调用函数的方式也没有改变,但是结果却是添加新功能后的结果。这就满足了线上的环境。
 
为什么要用嵌套函数:
大家可以尝试一下,去掉一层函数,那么将无法实现将test函数重新定义为wrapper函数的功能。那么执行结果除了添加新功能的结果,还会在执行一次主test函数。故,需要嵌套函数。
 
为什么要用返回值,为了重新给test定义,将wrapper赋值给test。
 
 
posted @ 2018-11-22 20:53  Dayle  阅读(284)  评论(0编辑  收藏  举报