闭包和装饰器

前言

在Python开发面试里面经常都会问到关于装饰器的使用,或者在笔试题里面实现用装饰器完成某一项修改功能。那装饰器到底是个什么东西?就是自如其名用来装饰的吗?但是对于程序来说,怎么进行装饰呢?

什么是闭包?

要理解什么是装饰器首先要了解什么是闭包。

闭包,字面意思就是一个封闭的包裹,这个包裹就是一个函数。而这个包裹里面的东西就是自由变量。直白一点,闭包就是一个函数,只不过这个函数可以访问另一个函数的作用域

例如,在Python3中,有如下这样一个函数:


最终运行结果如下:


可以看到在第一次调用inn()的时候,里面的函数inner()调用了函数外部的outer()函数的变量a。首先是打印输出变量的值,再对它进行加1的操作,也就是让它变成了2。而第二次调用的时候就是打印2。可以看到这个里面的函数调用了外层的函数的变量并对它进行操作

而在日常开发中,经常会有用到的一个功能就是:使用闭包实现不修改源码添加功能

比如,对下面一个函数

运行之后会在输出:

如果定义一个闭包,并修改函数:

最终的输出结果就是:

可以看到在使用功能1前后都加上启用和关闭日志功能的操作

什么是装饰器?

理解了闭包之后,那么接下来来讲讲装饰器。这里讲的“装饰”并不是我们日常生活当中像给房间里面放上一些好看的东西这种装饰,而是在已有某一功能的情况中对其进行增强或是增加。本质上装饰器就是一个闭包,只不过使用方式比闭包更加便捷

例如像在闭包里面提到的增加日志功能,也可以像这样使用

最终程序运行的效果也是一样的

为什么要用?

在修改代码的时候一直有一个原则就是不要删减源代码,否则可能会对原来的程序造成不可估测的影响。因为你没有办法知道这一环是不是其他环节的基础之类的,很有可能导致最终整个系统崩溃。所以在修改的时候宁可增加代码量,也不要对代码进行删减。

怎么用?

常用的像添加日志功能这种在上面已经有讲到了。那如果我是要进行传参呢?那怎么办?接下来就以一道笔者之前面试的时候接触到的使用装饰器的题目进行解答。

题目是对下面的函数进行修改,实现求(x+1)*(y+1)的效果

直接使用print(mul(4,5))的时候就会输出结果20

当我们为其加上一个装饰后

最终输出的结果就是30,也就是5*6

多个装饰器的执行顺序

有时候我们也要使用多个装饰器来修饰一个函数,这个时候装饰器函数的执行顺序分为(被装饰函数的)定义阶段以及(被装饰函数的)执行阶段

首先我们来看一个例子

首先在函数的定义阶段,就相当于:

fun=cost_time(fun)

fun=mylog(fun)

也就是:fun=mylog(cost_time(fun))

在定义阶段,先执行cost_time函数,再执行mylog函数

相反的,在调用执行的过程中,会先执行mylog函数,再执行cost_time函数

你可能感兴趣的:(闭包和装饰器)