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

终于弄明白了Python的装饰器(一)

时间:2023-03-25 21:49:16 Python

本系列文档:1.终于弄明白了Python的装饰器(一)2.终于弄明白了Python的装饰器(二)3.我终于弄懂了Python的装饰器(三)4.终于看懂了Python的装饰器(四)一、装饰器基础知识(什么是装饰器)Python的函数是对象要理解装饰器,首先要了解函数在Python中是对象。这有着重要的联系。让我们看一个简单的例子:defshout(word="yes"):returnword.capitalize()+"!"print(shout())#输出:“是的!”#作为一个对象,你可以像将函数赋值给变量scream=shout#注意我们不使用括号:我们不调用函数#我们将函数“shout”放入变量“scream”。#这意味着你可以从"scream"调用"shout":print(scream())#Output:'Yes!'#除其他事项外,这意味着您可以删除旧名称'shout',该函数仍然可以从'scream'访问delshouttry:print(shout())exceptNameErrorase:print(e)#output:"name'shout'未定义"print(scream())#输出:'是!'请记住这一点,我们很快就会回来。Python函数的另一个有趣的特性是它们可以在另一个函数中定义!deftalk():#你可以在“talk”中动态定义一个函数...defwhisper(word="yes"):returnword.lower()+"..."#...并且可以使用立即它。print(whisper())#每次调用“talk”时定义“whisper”,然后在“talk”中调用“whisper”。talk()#Output:#"yes..."#But"whisper"不存在于"talk"的定义之外:try:print(whisper())exceptNameErrorase:print(e)#Output:"name'whisper'isnotdefined"函数参考OK,你还应该读吗?现在是有趣的部分……您已经看到函数是对象。所以,函数:可以赋值给一个变量,可以在另一个函数中定义,这意味着一个函数可以返回另一个函数。defgetTalk(kind="shout"):#我们调用即时函数defshout(word="yes"):returnword.capitalize()+"!"defwhisper(word="yes"):返回单词。降低()+“......”;#thenwereturnitifkind=="shout":#我们不使用"()",所以我们没有调用函数,我们返回这个函数对象returnshoutelse:returnwhisper#获取函数并赋值它到一个变量:"talk"talk=getTalk()#你可以看到"talk"是一个函数对象:print(talk)#Output:#函数对象返回什么:print(talk())#outputs:是的!#如果你感到困惑,你甚至可以直接使用它:print(getTalk("whisper")())#outputs:是的......还有更多!如果你可以返回一个函数,你可以将其中一个作为参数传递:defdoSomethingBefore(func):print("IdoSomethingbeforethenIcallthefunctionyougaveme")print(func())doSomethingBefore(scream)#Output:#IdosomethingbeforethenIcallthefunctionyougaveme#Yes!好吧,您已经掌握了理解装饰器所需的所有信息。你看,装饰器是“包装器”,这意味着它们允许你在被装饰函数前后执行代码,而无需修改函数本身的代码内容。手工装饰你会知道如何手动完成:#装饰器是一个将另一个函数作为参数的函数defmy_shiny_new_decorator(a_function_to_decorate):#在内部,装饰器动态定义了一个函数:wrappers。#这个函数将被包裹在原函数之外,这样它就可以执行它之前和之后的代码。defthe_wrapper_around_the_original_function():#在调用原函数之前,将要执行的代码放在这里代码放在这里print("Afterthefunctionruns")#到目前为止,“a_function_to_decorate”还没有被执行。#我们返回刚刚创建的包装函数。#包装器包含要在代码前后执行的函数和代码。随时可用!returnthe_wrapper_around_the_original_function#现在,假设您创建了该函数,但不想再修改该函数。defa_stand_alone_function():print("我是独立函数,你敢修改我吗")a_stand_alone_function()#输出:我是独立函数,你敢修改我#所以,你可以装饰它扩展了它的行为。#只需将它传递给装饰器,它就会动态包装#你想要的任何代码,并返回给你准备好使用的新函数:function,你敢修改我#Afterthefunctionruns现在你可能希望a_stand_alone_function_decorated每次调用时都调用a_stand_alone_function。这个很简单,用a_stand_alone_function返回的函数重写my_shiny_new_decorator即可:#这正是装饰者所做的!装饰器揭秘下面是使用装饰器的语法:@my_shiny_new_decoratordefanother_stand_alone_function():print("Leavemealone")another_stand_alone_function()#Output:#Beforethefunctionruns#Leavemealone#AfterthefunctionrunsYes,That'sall.@decorator只是实现的捷径:another_stand_alone_function=my_shiny_new_decorator(another_stand_alone_function)装饰器只是装饰器设计模式的pythonic变体。Python中嵌入了几种经典的设计模式以简化开发(例如迭代器)。当然你可以积累装饰器:defbread(func):defwrapper():print("")func()print("<\______/>")returnwrapperdefingredients(func):defwrapper():print("#tomatoes#")func()print("~salad~")returnwrapperdefsandwich(food="--ham--"):print(food)sandwich()#输出:--ham--sandwich=bread(ingredients(sandwich))sandwich()#Output:##??#tomatoes##--ham--#~salad~#<\______/>使用Python装饰器语法:@bread@ingredientsdefsandwich(food="--ham--"):print(food)sandwich()#outputs:###tomatoes##--ham--#~salad~#<\______/>装饰器项目的设置顺序很重要,例如:@ingredients@breaddefstrange_sandwich(food="--ham--"):print(food)strange_sandwich()#outputs:##tomatoes###??--火腿--#<\______/>#~沙拉~