Python装饰器是很多Python初学者的面对的一道坎,对于只学过Python入门教程的人来说会觉得很难理解,学完后往往是似懂非懂,一段时间不接触,之前学的也就忘的差不多了。学习之路崎岖不平,希望我写的这个系列的文章能对大家有所帮助,让路途平坦顺畅些。
1. 什么是Python装饰器
好了现在言归正传,首先,在正式开讲前我们先来明确一个概念,究竟什么是装饰器?这里需要知道的是当我们对一个事物下定义时,从不同的角度就会有不同的理解。这里我们从装饰器的原理入手,先来下一个最基本的定义:
所谓装饰器就是一个可以接收callable 作为参数并返回另一个callable的callable。
Callable在这里指代可调用对象。所谓可调用对象就是可以在这个对象的末尾加上()从而执行对象内部代码块的对象。常见的callable有函数len(),方法str.lower(),类str()等。考虑到接下来我们对装饰器的讨论主要集中在函数上(后续的文章中会涉及到类装饰器,至于方法本质上不过是定义在类中的函数不用另外讨论),所以我们在这里也可以把装饰器理解成就是一个可以接收函数作为参数也可以返回函数的函数。
2. 函数是第一等对象
说了这么多,大家可能听着还是感觉有些不理解,不用着急这才刚刚开始。我现在来帮大家好好理解这最后一句话的含义。要理解这句话的含义大家首先要深刻的认识到在Python中函数是第一等的对象,明白了这个,其它的也就不难了。
在Python中数字、字符串、字典、列表等都是一等对象,它们都有如下特点:
1. 在运行时创建
2. 能赋值给变量或数据结构中的元素
3. 能作为参数传给函数
4. 能作为函数的返回结果
事实上这些特点函数也都具备,下面逐条来说明:
1)在运行时创建
2)能赋值给变量或数据结构中的元素
3)能作为参数传给函数,这里用Python自带的高阶函数举例
4)能作为函数的返回结果
3. 函数输入输出的4种情况
关于函数是第一等对象这个事我们就介绍到这,有了这些背景知识我们接下来继续给大家讲解什么是装饰器。在前面我们提到装饰器就是一个可以接收函数作为参数也可以返回函数的函数。我们把函数作为一个中间装置,两头分别是输入和输出,那么我们现在就可以归纳出4种情况。
1. 输入普通对象,输出普通对象;
2. 输入普通对象,输出函数;
3. 输入函数,输出普通对象;
4. 输入函数,输出函数;
第一种情况是我们熟知的,这是的函数就是那种最常见到的普通函数,这里就不再赘述。
再说说第二种情况,输入一个普通对象,返回一个函数。返回函数这个我在前面的示例中也有提到。这里补充一个要注意的点:此时返回的那个函数是一个闭包函数。闭包指延伸了作用域的函数,它能访问定义体之外定义的非全局变量。
第三种情况是输入一个函数,返回一个普通对象。如果只是为了返回一个普通对象,我们为什么要输入一个函数呢?这里要明白的是函数它是对一段代码的封装,从外面看函数,它是一个行动,我们传入函数就是要利用这个行为,帮助我们定制化输出的结果。
第四种情况就是我们要讲的装饰器了�
4. Python装饰器基础
好啦经过前面的种种铺垫我们现在终于进入到正题——装饰器了。先来个简单的,循序渐进嘛~
下面这个装饰器,可能是最简单的装饰器了,虽然简单到没什么实际用途,但用来学习还是挺不错的,看着它,再想想装饰器的定义,对装饰器的理解是不是更清楚了?
之前我们有说到函数就是一个封装后的代码块,里面是一个行为。装饰器的作用就是让你重用这个代码块,同时在一定程度上改变这个代码块的行为。既然要改变代码块的行为,那么输入的代码块和输出的肯定不一样,不然就和我们上面写的那个装饰器一样了,虽然是个装饰器,但起不到装饰的效果。
改变代码行为的方法大体可分成两种,一种是直接在原函数上进行修改然后返回原函数,另一种更常见是通过返回一个新定义的函数来实现间接的修改,这个新的函数为了具备原函数的功能,往往在定义时就把作为参数的原函数包括在内,同时把之后调用自己时接收到的参数原封不动的传递给原函数。
第一种情况出现的不多,因为即便对于装饰器而言函数也是一个黑盒,我们不好通过直接修改函数内部的代码来达到装饰的目的,我们这里先简单来看个小例子
这个装饰器会修改被装饰函数的__doc__属性,然后返回修改后的原来的函数对象
下面要说的是第二种情况,也是本次要讲的重点。前面说过代码的行为是被封装好的,要改不易。装饰器改变代码块行为的做法其实就是取了个巧,间接的做到了这一点,这种做法形象的说就叫做偷梁换柱。表面上看装饰后的函数和原函数的调用方法是一样的,传的参数也是一样的,但装饰前和装饰后调用的函数已经不是同一个了。
小结
看到这里相信大家对什么是装饰器应该已经有了一个清晰的认识,虽然我们才刚刚起步,但有了这些基础后面的内容学起来也不会那么难了。有同学可能会奇怪@去哪了,其实@只是语法糖,并不是构造一个装饰器所必须的。我们今天只是专注于了解装饰器到底是怎么一回事,其它不必要的内容先不放进来,免得大家犯迷糊。后续关于装饰器的内容会逐步的呈现在大家面前,不要错过哦~