1。Python装饰器的叠加使用最近有同学问Python也有类似Java的@xxxx语法。这是什么意思?现在我来回答这个问题。Java中的@xxxx语法是注解(Annotation),而Python中的@xxxx语法是装饰器(decorator)。尽管它们在语法上相似,但它们的功能却完全不同。Java的注解相当于句法元素(方法、类、接口等)的元数据。Python的装饰器是对Python函数(方法)的包装器,现在举个例子。@makebold@makeitalicdefsay():return"Hello"print(say()))这段代码对say函数使用了两个装饰器:@makebold和@makeitalic,并且是叠加状态。@makeitalic将首先作用于say函数,然后@makebold将作用于@makeitalic装饰器的结果。这两个装饰器分别用...和...包裹了say函数返回的字符串,所以这段代码的执行结果如下:你好,但是直接执行这段代码肯定会报错,因为这两个装饰器还没有定义,让我们看看如何定义这两个装饰器。2.定义Python装饰器装饰器本身就是一个普通的Python函数,但是函数的参数需要是一个函数类型(通常传递给被装饰的函数),定义形式如下:Hello现在定义上面给出的两个装饰器:fromfunctoolsimportwrapsdefmakebold(fn):@wraps(fn)defmakebold_wrapped(*args,**kwargs):return""+fn(*args,**kwargs)+""returnmakebold_wrappeddefmakeitalic(fn):@wraps(fn)defmakeitalic_wrapped(*args,**kwargs):return""+fn(*args,**kwargs)+"”returnmakeitalic_wrapped显然,makebold和makeitalic是两个普通的Python函数,函数内部还定义了另外两个函数,将这两个函数作为返回值返回。这个用到了wraps函数,这个函数其实可以省略,但是会有一些副作用。当使用@makebold和@makeitalic修饰一个函数时,被修饰的函数会被传递给makebold函数和makeitalic函数,也就是说fn参数是被修饰的函数。当外部调用修饰函数时,实际调用的是装饰器返回的函数,即makebold_wrapped和makeitalic_wrapped,这会导致修饰函数的属性发生变化,比如函数名、函数文档等,这可以先删除。@wraps,执行如下代码:@makeitalic@makebolddefsay():return"Hello"print(say.__name__)#输出函数名会输出如下内容:makebold_wrapped由于最后使用了@makebold装饰器,所以输出是makebold函数返回的makebold_wrapped函数的名称。如果添加@wraps,say将被输出。需要注意的是,wraps函数需要通过装饰器来调用,实际上相当于在@makebold外面包裹了一层装饰器(wraps)。3.理解Python函数现在我们已经学会了如何自定义Python装饰器,但是我们应该如何理解装饰器呢?原理是什么?要理解Python装饰器,首先应该知道Python函数是对象。看下面的例子:defshout(word="yes"):returnword.capitalize()#Output:Yesprint(shout())#将shout函数赋给另一个变量,这里不用括号,#所以不用调用function,将函数赋值给另一个变量,即给函数起一个别名scream=shout#可以用scream来调用shout函数#Output:Yesprint(scream())#目前同一个函数有两个引用:screamandshout,youcanusedeldeleteareferencedelshouttry:#引用删除后,函数无法通过引用调用print(shout())exceptNameError:print(e)#函数仍然可以通过引用调用另一个参考#Output:Yesprint(scream())这段代码演示了函数作为对象的使用。如果添加一对括号,则调用该函数。如果不加一对括号,函数就是一个对象,可以赋值给另一个变量,也可以作为函数参数值传入函数。由于Python函数本身是一个对象,所以可以在任何地方定义,包括函数内容。这是Python内置函数。代码如下:deftalk():#Inlinefunctiondefwhisper(word="YES"):returnword.lower()+"..."#调用内嵌函数print(whisper())#Calltalk,thewhispertalk函数内部调用#Output:yes...talk()try:#但是whisper函数不在talk函数外部可以看出调用会抛出异常print(whisper())exceptNameError:print(e)现在总结一下,Python函数的特点如下:(1)函数本身可以赋值给一个变量,或者作为参数值传入Function(方法);(2)可以在函数(方法)内部定义;有了这两个特性,就意味着该函数可以被另一个函数返回,看下面的代码:defgetTalk(kind="shout"):#定义第一个内置函数defshout(word="yes"):returnword。capitalize()+"!"#定义第二个内建函数defwhisper(word="yes"):returnword.lower()+"..."#根据参数值返回具体函数ifkind=="shout":#这里没有用一对括号,所以不是调用函数,而是返回函数本身:
