2019/10/09 02-无参装饰器***

有个需求
2019/10/09 02-无参装饰器***_第1张图片
加法的函数就完成加法即可,没必要print,如果减法,你也加了print,print你就可以写成参数
对add来讲,跟主要功能没有关系,是附加的功能,需要的时候加上,不需要的时候摘掉,写死了就是硬编码
但是一般add函数就做add
打印不是该你负责的事情,但是如果又需要你有这个功能,就很矛盾
在这里插入图片描述
想要变成一种附加的或者增强的功能,需要就加,不需要就忽略2019/10/09 02-无参装饰器***_第2张图片
** __name__就是这个函数对象是什么名字**2019/10/09 02-无参装饰器***_第3张图片
这样写还是有很多好处的,相当于通用的了,add的主要业务是不包含打印的,这样打印就成为一种附加的功能,不是它的主要业务2019/10/09 02-无参装饰器***_第4张图片改成xy就把参数搞定了2019/10/09 02-无参装饰器***_第5张图片
想要这两个也通用,也打印2019/10/09 02-无参装饰器***_第6张图片
函数传参有两种,关键字和位置传参,不管keyword-only还是其他,传参只有两种方式
2019/10/09 02-无参装饰器***_第7张图片
还需要解构
2019/10/09 02-无参装饰器***_第8张图片
上面的是形参定义,下面是参数解构,两码事(疑问,这样传就符合要求 了吗)
在这里插入图片描述
具体参数对不对还是需要fn来管,这个参数对不对不是以你的logger来决定的,由你原来的业务函数fn来决定实参是不是它想要的,fn(*args)解构之后相当于add(4,5)2019/10/09 02-无参装饰器***_第9张图片
输入的参数对不对,是用add来判断的,2019/10/09 02-无参装饰器***_第10张图片
可不可把b打印一下
logger函数只是记录一下并不对之前的信息做任何修改

2019/10/09 02-无参装饰器***_第11张图片
开始柯里化
整体向右挪,先让外层调用内存

2019/10/09 02-无参装饰器***_第12张图片
logger(add)返回函数,给fn 调用fn(),到目前为止做了一次柯里化

进一步做处理,把这一块单独拿开
2019/10/09 02-无参装饰器***_第13张图片
现在针对add函数研究
2019/10/09 02-无参装饰器***_第14张图片在这里插入图片描述
*既然成功执行说明add是可以被覆盖的,那么原来的add消失了吗
下面的add,等于赋值即重新定义,这个标识符相当于记录inner函数对象
add (4,5)相当于调用inner(4,5)传给args了
该打印打印
fn(args)4,5在这里解开,fn还记得这个之前的add函数,形成了闭包,原来的add爱谁谁

2019/10/09 02-无参装饰器***_第15张图片
这个闭包的fn记录着曾经的add对应的内存中的函数对象2019/10/09 02-无参装饰器***_第16张图片
传递,4,5,返回9 ret=9,返回给你
2019/10/09 02-无参装饰器***_第17张图片
用到了嵌套函数,作用域,闭包,还用到了函数定义的本质,还用到了可变参数,参数解构

再做一次变形,装饰器,复制一下,准备修改这段代码
2019/10/09 02-无参装饰器***_第18张图片2019/10/09 02-无参装饰器***_第19张图片
这个地方@logger 等价为logger(add)=>add就是inner
logger是个函数,前面加@符号,就能将下面函数的标识符,作为参数传进来
add作为参数,logger(add)赋给同名标识符add
相当于给logger函数传参数,计算来的结果赋值给同名的标识符add
所以add 就等于inner

2019/10/09 02-无参装饰器***_第20张图片
fn记得add,所以传进去,4,5相加
但是用的时候logger函数需要放在前面,否则后面@使用的时候会报错的
2019/10/09 02-无参装饰器***_第21张图片直接执行相当于定义两个函数,没有调用,相当于inner函数没有调用
2019/10/09 02-无参装饰器***_第22张图片在调用的过程中,你以为调用的是add实际调用的是inner,会给你一些功能增强,而且不影响原来的功能,这个就是装饰器
2019/10/09 02-无参装饰器***_第23张图片
wrapper包装者,add就是被包装者
装饰器一般不改变原来的功能

2019/10/09 02-无参装饰器***_第24张图片
add原来没有print功能,给它增强,可变参数,参数解构,之后用到柯里化,变成2层函数,调用的方式就改变了,
做等价
等价之后,才做了装饰器语法
这是个装饰器例子,必须看懂,
写的时候可以把等价式写在后面

2019/10/09 02-无参装饰器***_第25张图片
把名称前面加add,就能把下面的标识符,提进来作为参数,它的返回值会重新覆盖这个标识符,至于覆盖之后看你怎么写,
2019/10/09 02-无参装饰器***_第26张图片

2019/10/09 02-无参装饰器***_第27张图片
参数写死 先改变成下面,包括如何解构2019/10/09 02-无参装饰器***_第28张图片
换一种写法写成这样,柯里化就能写成这样
写成另外的形态,因为有闭包,原来的fn记住了add
2019/10/09 02-无参装饰器***_第29张图片
有 了这种写法就可以用装饰器语法,不过函数定义要调个顺序
2019/10/09 02-无参装饰器***_第30张图片
装饰器的logger会把下面的标识符作为参数,并且得到的值赋给这个add标识符2019/10/09 02-无参装饰器***_第31张图片2019/10/09 02-无参装饰器***_第32张图片
无参装饰器
这一处的装饰器定义是不准确的,只是方便理解
现在来看,
装饰器是一个函数,
函数作为它的形参
返回值也是一个函数
可以使用@functionname方式,简化调用
实际上是个高阶函数

2019/10/09 02-无参装饰器***_第33张图片
在函数调用之前可以做一些增强,函数调用后也可以做一些增强,最后函数的返回值
这就是稍微全面点的装饰器的写法
2019/10/09 02-无参装饰器***_第34张图片
主要功能由业务函数完成,缺什么填什么,函数封装,各司其职,不互相干扰
2019/10/09 02-无参装饰器***_第35张图片
可以通过这个功能,简单记录函数的耗时时间
写代码最后执行的肯定都是函数
尤其执行慢的函数必须要知道
现在就可以在某些函数上面加个装饰器就完了,就可以通过这个简单记录,来表现系统的问题在哪里

2019/10/09 02-无参装饰器***_第36张图片
装饰器实际上就是画框,画框就是装饰器函数,加的就是被包装函数(被增强),画
要在前面加玻璃板,后面加底称,前功能增强,后置功能增强,拿画框卡起来
,这个装饰器是没有破坏原来的函数的
明天不需要可以拿掉,安装另外的功能,但是装饰器可以套装饰器
可以理解为外面黑画框,外面套红画框,里面画还是本身,只不过加了装饰而已

装饰器是对原有函数功能进行一些增强,一般情况下不会改变原来函数的功能,不会在函数内部进行任何硬编码2019/10/09 02-无参装饰器***_第37张图片

你可能感兴趣的:(2019/10/09 02-无参装饰器***)