python装饰器详解

原创
2017/01/06 19:20
阅读数 65

python的装饰器其实是一个语法糖,第一行是@跟着一个表达式;第二行必须以def或者class起始(亦即函数或者class的定义)。

python的装饰器,必须是可调用的对象,而且必须是可以以一个参数进行调用。注意,对返回参数的个数是不做限制的!

那么,python中有几种可调用对象呢?大致有四种:

1)函数对象,这个不用多说什么了吧;
2)类对象,我们生成类实例的时候,都是用类对象调用生成的;
3)类的三种方法:实例方法、类方法、静态方法;
4)如果类实现了`__call__`方法,则类的实例对象也是可调用的;

装饰器本质上就是一个语法糖,它等价于先定义了函数/类之后,将函数对象/类对象作为参数调用装饰器,然后将返回值赋给原本代表函数对象/类对象的变量。

事实上,只要装饰器能够成功执行,不管它如何处理的,python都不会报错。即使返回值不是同类的函数或者类对象,而是其它的什么东西,比如基本类型,乃至列表/元组都无所谓。

好了,我们现在差不多,就知道装饰器这玩意是一个多么自由的东西了。其实python里面n多东西都这么自由。

根据装饰器的输入和输出,我们可以将装饰器分成如下几类

1)吃进一个函数,吐出一个修饰过的函数。
    这是我们自己最常写的一种装饰器了,通常我们通过装饰器,来进行log、缓存、类型检验、错误捕捉等等。

2)吃进一个函数,返回一个class对象。
    这种情况比较罕见,至少我没有见过。

3)吃进一个函数,吐出一个class的实例。
    最典型的,比如property,它可以吃进一个函数,返回一个描述器的实例(注意返回的实例的身份肯定是类的属性)。staticmethod和classmethod也是一样的道理。
    还有一种情况,也就是返回一个实现了`__call__`方法的class对象的实例。这种相当于一个可更新环境的闭包,有时候挺有用。
    
4)吃进一个函数,吐出一个不可调用对象。
    基本上,这是起到一个提前计算的作用。比如说一个装饰器可以接受一个函数,然后预先计算出函数的返回值,然后直接将返回值赋给原本代表函数对象/类对象的变量。
    
5)吃进一个class对象,吐出一个函数。
    比如返回一个可以使用参数来返回该class对象的实例的函数,但同时也进行log、缓存、类型检验、错误捕捉等等。
    
6)吃进一个class对象,吐出一个class对象。
    和第一种类似,只不过是对class对象进行完善,比如functools.total_ordering,它就是可以完善class对象的比较运算的魔术方法。
    

展开阅读全文
加载中

作者的其它热门文章

打赏
0
2 收藏
分享
打赏
0 评论
2 收藏
0
分享
返回顶部
顶部