Python装饰器的理解

装饰器是Python中广泛运用的一种技术,主要可以起到代码复用减小代码量,增强代码的扩展性的作用。

要理解装饰器先要理解两个概念,闭包和参数寻找优先级。

闭包可以参看上一篇博客的介绍,参数寻找优先级概念如下:

当我们使用到某个参数a时,会自动按顺序去寻找a的定义,在python中是可以在多处定义a的值且调用的值还不一样,这就是由于参数寻找优先级的不同导致的,参数寻找优先级可以用四个字母(按优先级别从高到低)来表示:LEGB

L:Local    表示局部参数定义,如函数A中调用的a,在A中a = ? 则为局部参数;

E:Enclosing   表示嵌入级参数,如函数A中定义了a,同时函数A中定义或调用了函数B,在B中使用值a时,则为嵌入级参数

G:global   表示全局参数,一般定义在主函数中

B:Biult-in Python内建参数


介绍完相关概念,本文讲一下技术背景,即为什么要有装饰器这种东西:

在python中,万物皆对象,函数也不例外,因而它也可以作为参数传递到函数中:  

eg: 

def A(func_B, *args):

      for i in args:

            i+=1

      return func_B(args)

def B(*args):

      return print(args)

但是通常,我们希望定义尽量少的外部函数,因而会选择将函数调用以嵌套函数的形式写出:

eg: 

def A( *args):

      for i in args:

            i++

      def B():

             print(args)

      return B

C = A(1,2,3)

C()

返回结果:2,3,4

B(1,2)      结果会报错B未定义;

此时B则是一个闭包,对B而言,args则为捆绑的自由变量。对整个主函数而言,B是一个携带自由变量args的包裹,是一个定制函数。该定制函数还可以通过C()接收其它变量。

引申问题1:若要在B中引用A中的值则需要进行nonlocal声明,若要进行全局变量的修改则需要进行global声明。

引申问题2:若在函数内部修改值,外部也随之改变则为引用传递,否则则为值传递。字典和列表为引用传递,其余为值传递。

上述为闭包的一种用法:通过C=A(args)定制包裹B。

闭包的另一种用途是对函数进行装饰,即在定义函数B之后,对函数B进行修饰:

eg:


此时闭包in_dec(*arg)就是对函数my_sum的一个修饰与增强,或者说是扩展。

其实质就是我们所说的装饰器,Python不过是使用语法糖@将其包装了一下,

eg:使用语法糖的装饰器如下:


@dec 即是调用dec,而且同时将返回的函数func(*arg)调换为后面的my_sum(*arg)。

这个就是装饰器的本质。

在此处该装饰器是用于判断输入的内容是否合法,若是业务中需要反复用到某一功能修饰,如在增删查改中,每次操作都要先进行合法性判断,便可以使用装饰器功能,对判断过程进行封装,而后反复调用即可。


猜你喜欢

转载自blog.csdn.net/airuio/article/details/80489433