装饰器基本概念
A.装饰器的构成
一般可调用对象都可以构成装饰器:函数(方法)/实现__call__方法的实例
B.可装饰对象
一般可调用对象都可以被装饰:函数(方法)/实现__call__方法的实例
C.装饰器的功能
实现为可调用对象动态增加代码,装饰代码可以根据需要添加在被装饰对象执
行前或执行后.
D.实现机理
1.装饰器先发生调用行为,将被装饰对象作为参数传给装饰器,在把被装饰对
象替换为装饰器的返回值
2.把@decorator放到被装饰对象f的定义处相当执行语f=decorator(f)
无参装饰器
A.无参函数/方法装饰器
1.通常,装饰器通过@接收被装饰对象进入装饰器的命名空间中,定义一个新
的可调用对象(一般的,应与被装饰对象类型相同,形参至少要可以接收被
装饰对象的参数,也可以有因添加新功能所需的参数)
2.在此新可调用对象中调用传入的被装饰对象(注意调用时要利用新可调用对象接收的参数),再为其加上补充代码,并使用@functools.wraps(被装饰对象)将新可调用对象的属性和方法替换为被装饰对象的属性和方法,最后返回新的可调用对象即可
3.即把被装饰对象替换为了在装饰器中新定义的可调用对象,调用时参数格式应以此对象形参格式为准
B.无参类装饰器(不常用)
1.通常,使用实例构造方法init(self,f)接收被装饰对象f,并将f绑定在此类的实例上,从而进入实例的命名空间,再创建一个实例的call(self,参数列表)方法<参数列表至少要可以接收被装饰对象的参数,也可以有因添加新功能所需的参数>在call方法中调用绑定在实例上的被装饰对象self.f(注意调用时要利用新可调用对象接收的参数),再为其加上补充代码即可,不用返回值.调用时参数格式应以此对象call方法形参格式为准
2.注意:类装饰器发生装饰行为时会发生调用,其调用的返回值一定是此类装饰器的一个实例,所以使用类装饰器后的被装饰对象都会变为类装饰器的一个实例
含参装饰器(创建外壳即可)
A.说明
创建一个可调用对象,该可调用对象可以接收参数,并将装饰器定义在该可调用对象中然后返回该装饰器,由于装饰器在该可调用对象中定义,故可以使用该可调用对象接收的参数,实现含参装饰器。
注意
1.离被装饰对象越近越早执行装饰。最外层装饰返回的对象为最终装饰结果。
2.在被装饰函数/方法/类的定义之后,重新定义了同名函数(方法)/类,则装饰无效,按后面的定义执行。
3.在装饰器返回对象的前面加上@functools.wraps(f),帮助被装饰对象f保留自己原有属性(仅对函数/方法装饰器有效)