装饰器:在原本的程序基础上新加一些功能(比如判断余额、次数登记等)后伪装成原来的程序。
多层装饰器:
def makeBole(fn): ============>此处是函数做装饰器,另外还可以用类做装饰器
def wrapped():
return "<b>" + fn() + "</b>"
return wrapped
def makeItalic(fn):
def wrapped(*args,**kwargs):
return "<i>" + fn(*args,**kwargs) + "</i>" ========>装饰器对有参数函数进行装饰,用*将元组拆开传递给真实函数。遇到这种传递不定长参数给另外一个函数时可以用这种万能方法(即:在参数传递通道中使用*args,*kwargs)。
return wrapped
def canshu(fn,a,b):
print(a,b)
return fn()
@canshu(11,22) ========>带有参数的装饰器
@makeBold =========>等价于test3 = makeBole(test3),注意:makeBole(test3)中的test3为下面@makeItalic装饰过后的test3,而非原始test3();
当解释器执行到这行时会判断下面是否是一个装饰器,如果是会先等下面装饰完再执行。(装饰器下面只能跟函数和装饰器,跟变量会出错)
@makeItalic =========>等价于test3 = makeItalic(test3) =======>装饰器必须在装饰时就执行一遍,因为装饰器里面包含被装饰函数内存地址,该地址需要提前加载到内存中,不然装饰器中被装饰函数地址会被指
向装饰后的地址,从而形成死循环(即:装饰器中调用test3()时调用的如果是被装饰后的test3则会陷入死循环,所以装饰器需要在装饰时就执行一遍以加载至内存中,以后装饰器中调用test3时就
拿内存中的这一份)。
def test3(a,b,c):
return "hello word"+a+b+c
print(test3(11,22,33)) =========>输出结果为:<b><i>hello word112233</i></b>
类做装饰器(没想明白函数做装饰器和类做装饰器各有什么优劣势):
class abc(object):
def __init__(self,func):
print('----装饰的时候这里会被执行哦------')
self.__func = func
def __call__(self): =========> __call__的作用是当执行“对象()”时会调用该方法(即:通过这个方法可以把类当做函数去执行)。
print('----装饰器中的功能-----')
self.__func()
@abc ========>此处相当于 test = abc(test) ,即test指向abc()创建出来的一个对象。
def test():
print('---test---')
test() ========> 此处会调用对象test中的__call__方法,即等价于:test.__call__()。
函数做装饰器的本质是把被装饰函数重定向到另外一个函数上去,然后该函数再重定向到自己的闭包中,在闭包中添加一些“佐料”后再重定向回最原始的被装饰函数(即:添加“佐料”是在闭包中完成)。
类做装饰器的本质是把被装饰函数重定向到一个对象上去,然后利用该对象的__call__()方法对其添加“佐料”后再返回原始的被装饰函数(即:添加“佐料”是在__call__()方法中完成)