当前位置: 首页 > 后端技术 > Python

Python之路day14-decorator_多层装饰器

时间:2023-03-26 18:54:56 Python

前言今天学习了装饰器的用法,很久以前就学过。。。总结一下:今天主要学习了装饰器的作用和用法装饰器很重要,它是推荐了解。1.装饰器的概念装饰器顾名思义就是在不改变函数内部代码的情况下,对函数进行装饰和扩展。去掉装饰器不影响原来函数的功能,加上装饰器可以扩展一个函数。例如:装饰品可以比作化妆品,化妆品可以让脸更漂亮,但是擦掉化妆品,脸还是脸。只是用化妆品来装饰你的脸,让它看起来更好看,根本不会改变脸的属性。有人说装饰器有什么用?装饰器完全符合代码开闭原则。什么是代码开闭原则?关闭:对修改关闭。在扩展代码的情况下,不能修改原函数的代码。开放性:允许对已经设计好的代码进行功能扩展。想象一个场景。今天是节气,老板要你给网站扩展充1送1的功能。你的方法是硬扩展、软扩展还是智能扩展?详细听我说defcharge_money(pay_sum):print(f"充值到:{pay_sum}元")returnTrue#1.做事件前charge_money(666)#已经充值:666元1)硬扩:defcharge_money(pay_sum):print(f"活动赠送:{pay_sum}元")pay_sum=pay_sum*2print(f"充值到:{pay_sum}元")returnTrue#2.对活动charge_money做硬扩展(666)#活动礼物:666元#充值到账号:1332元这里有个问题,就是原来功能的内容被改了,不符合关闭原则。2)软扩:#3.软扩defsalse_activity(pay_sum):print(f"Theeventgaveaway:{pay_sum}yuan")#保存代码:更新数据库中用户的金额returnTruedefcharge_money(pay_sum):print(f"Rechargetoaccount:{pay_sum}yuan")#这里保存代码:更新数据库中的用户金额returnTruesalse_activity(666)charge_money(666)#活动给了:666元#充值到账户:666元软扩展是在原有的基础上增加了新的功能,相当于扩展了一个功能。但是还有一个问题。如果你同时给n个充值函数添加一个充值一送一的活动,那么你需要写n次salse_activity(666),非常难看。那么就请来今天的主角装修师登场吧。3)智能扩展:#智能扩展装饰器defsalse_activity(func):"""其实是一个闭包"""definner(pay_sum):print(f"活动给出:{pay_sum}元")#保存到这里去代码:更新数据库中用户的金额res=func(pay_sum)returnresreturninnerdefcharge_money(pay_sum):print(f"Rechargearrives:{pay_sum}yuan")#保存代码:更新用户的金额在数据库中returnTruecharge_money=salse_activity(charge_money)charge_money(666)#活动礼物:666元#充值到账:666元使用Python装饰器语法糖变体:#decorator语法糖defsalse_activity(func):"""其实是theclosure"""definner(pay_sum):print(f"Theeventgaveaway:{pay_sum}yuan")#保存代码:更新数据库中用户的金额res=func(pay_sum)returnresreturninner@salse_activity#等于charge_money=salse_activity(charge_money)defcharge_money(pay_sum):print(f"充值到:{pay_sum}元")#保存这里的代码:更新数据库的用户金额returnTruecharge_money(666)#活动礼物了:666元#充值账户:666元装饰器的介绍到此结束,下面介绍装饰器的具体用法。2.装饰器参数装饰器的参数一般都是*args和**kwargs组合在一起,看起来更简洁明了。#初始化defdecorate_A(func):print("我是装饰器A")definner_A(*args):print("装饰器A被调用")res=func(*args)print(f"resA:{res}")returnres+"+装饰器A返回值"returninner_Adefdecorate_B(func):print("我是装饰器B")definner_B(*args):print("装饰器B被调用")res=func(*args)print(f"resB:{res}")returnresreturninner_B给函数添加装饰器,调用参数:@decorate_A#main_func=decorate_A(main_func)=inner_Adefmain_func(*args):print("我是主function")print(args)returnTruemain_func(*[1,2,3],4,*(5,6,7))"""我是decoratorA调用了DecoratorA我是主函数(1,2,3,4,5,6,7)resA:True"""上面涉及到*args,不明白的可以看我的另一篇博客:[argsand*args](),3.Multi-layerdecorators多层装饰器从下到上依次执行。需要注意的是,被装饰函数名引用的函数在装饰器中总是被内部函数代替。#3.main_func=decorate_A(inner_B)(*args)@decorate_A#2.main_func=decorate_A(inner_B)=inner_A@decorate_B#1.main_func=decorate_B(main_func)=inner_Bdefmain_func(*args):print("我是mainfunction")print(args)return"mainfunction"res=main_func(*[1,2,3],4,*(5,6,7))print(res)"""我是decoratorBI是decoratorA.调用装饰器A.调用装饰器B.我是主函数main_func:(1,2,3,4,5,6,7)resB:TrueresA:True主函数+装饰器A返回值"""解释一下上面两个装饰器是怎么调用的。首先:调用函数,main_func(*[1,2,3],4,*(5,6,7))装饰器自下而上执行,先执行@decorate_B,main_func变为main_func=decorate_B(main_func)=inner_B。打印结果分析:这一步因为调用了decorate_B函数,所以打印出我是装饰者B,然后执行装饰者@decorate_A。这时候有main_func=decorate_A(main_func),但是在装饰器的前一步,main_func已经变成了inner_B,都是main_func=decorate_A(inner_B)。打印结果分析:这一步因为调用了decorate_A函数,所以打印出我是装饰者A,最后还有main_func=decorate_A(inner_B)(*args)。打印结果分析:1)调用函数main_func时,先执行函数inner_A,然后调用打印装饰器A。2)然后执行传入的参数inner_B函数,此时打印装饰器B被调用。3)执行inner_B函数中的函数其实就是修饰函数main_func,打印我是main函数,然后打印main_func:(1,2,3,4,5,6,7)。讲解后总结:装饰器很重要。个人觉得装饰器的设计确实很巧妙,但是有点让人费解,难以理解。建议多看多练多总结。参考链接:https://www.zwjjiaozhu.top/20...