装饰器简介以及多个装饰器执行顺序

 装饰器是Python用于封装函数或类的代码工具,是Python函数的高级特性之一。其主要功能是使某个函数在不需要做任何变动的前提下增加额外功能,即对某个函数进行功能”装饰“;主要作用是可以提高代码的可读性、简洁性以及扩展性,常用于后期功能升级;具体做法是将一些特定或者通用的方法写成装饰器,在待装饰函数定义前加上@+装饰器名称。

 

在自己编写装饰器之前,应注意一下几点:

1. 装饰器本质是一个函数,可称之为函数装饰器;

2. 装饰器也是一个闭包,即在非全局范围内定义的函数可以引用其外围空间中的变量;

3. 装饰器以一个函数作为参数,并且返回值也是一个函数;

4. 装饰器不能修改被装饰的函数代码;不能修改被装饰函数的调用方式;

常见装饰器示例如下(给一个函数增加计时器功能):

                               图1

扫描二维码关注公众号,回复: 5835055 查看本文章

执行结果如下所示:

                               图2

当一个函数需要增加多个功能时,此时需给原函数注入多个装饰器。此处的重难点在于多个装饰器的函数调用顺序。以下将围绕下面这个例子展开介绍:

                                图3

上面代码首先定义了两个函数(装饰器): decotator_one, decotator_two, 这两个函数实现的功能是:接收函数func作为参数然后返回创建的另一个函数inner_one或inner_two,在这两个创建的函数中分别调用被装饰函数func。紧接着定义了函数 f ,并采用上面定义的 decotator_one, decotator_two 作为装饰函数,最后再以1作为参数调用装饰后的函数 f 。

多个装饰器执行的顺序为自下而上,即从最后一个装饰器开始,执行到第一个装饰器。此时如果按照此原则判断,执行的结果应该为:

                                图4

但实际的运行结果为:

                                图5

现将具体原因整理如下:

1)区分函数和函数调用

上述代码中f为函数, f(1) 为函数调用,后者是对前者传入参数进行求值的结果。 f 是指代一个函数对象,它的值是函数本身, f(1) 是对函数的调用,它的值是调用的结果。类似地, 函数decorator_one返回的是个函数对象 inner_one ,函数对象 inner_one是函数decorator_one内部定义的。在 inner_one 里调用了函数 func ,将 func 的调用结果作为值返回。

(2)装饰器函数在被装饰函数定义好后立即执行

  

               图6                                          图7

上述两段代码是等价的。当解释器执行上述代码时, decorator_one 已经被调用,它以函数 f 作为参数, 返回它内部生成的一个函数,所以此后 f 指代的是 decorater_one 里面返回的 inner_one 。所以当以后调用 f 时,实际上相当于调用 inner_one,传给 f 的参数会传给 inner_one , 在调用 inner_one 时会把接收到的参数传给 inner_one 里的 func 即 f ,最后返回的是 f 调用的值。

 

3程序代码解释说明:

当解释器执行上述代码至位置1时,会按照从下到上的顺序依次调用装饰器,首先调用装饰器decorator_one ,此时会输出对应的 Get in decorator_one,同时 f 指代decorator_one 函数里的 inner_one;紧接着调用装饰器decorator_two ,并输出 Get in decorator_two,f 指代 decorator_two 里的 inner_two。当解释器执行上述代码至位置2时,即对 f 传入参数1进行调用时,inner_b 首先被调用,它会先打印 Get in inner_two ,然后调用 inner_one, 打印 Get in inner_one, 最后在 inner_one内部调用的原来的 f, 并且将结果作为最终的返回。

 

总结:

1. 装饰器函数在被装饰函数定义好后立即从下往上执行。

2. 函数调用时从上到下执行。

3. 最后执行被装饰函数,即函数本身。

猜你喜欢

转载自www.cnblogs.com/Despacito-lgq/p/10682659.html
今日推荐