作者:平山
http://blog.51cto.com/2681882/2117746
一 什么是装饰器?
正如其名,装饰器的作用是为已经存在的对象增加额外功能(装饰),由此可使已有函数在无需代码改动的情况下增加额外功能;装饰器的本质是嵌套的函数且返回函数对象,即闭包。有关闭包的概念,可参考
《理解Python中的闭包》
一文。
二 装饰器应用场景举例
在介绍装饰器之前,我们思考下遇到如下场景时的解决思路,然后在此基础上,描述装饰器的意义和旨在解决哪些问题。
假如我们的func函数已经在使用,而且工作的挺好,func函数如下:
然而,某天针对该函数有新需求提出,暂时命名为需求1:为func函数增加性能度量,即测量函数的执行耗时。
针对需求1,一种可以简单理解的实现形式如下:
从实现来看,满足了需求1,但如果其余的函数也提出了类似的需求,如func1、func2都需要增加耗时测量,按上面的实现方式,func1、func2也需要在原功能前后增加time.time()代码,这样就造成了代码重复和冗余。
针对代码重复的问题,另一种实现方式是,定义一个专用的耗时测量函数,当需要测量某个函数时,直接将被测函数作为该测量函数的入参,实现形式如下:
从上面实现来看,功能耗时统计的代码被抽离并定义在共用函数count_time里,当需要测量某个函数时,直接调用该count_time函数即可。
但这种实现也是有问题的,需求是希望直接调用func()函数即可完成对功能耗时的测量,但目前的实现方式,需要使用另外一个函数count_time,显然改变了函数的调用方式。
三 装饰器为原有函数增加额外功能
针对上面场景描述及问题分析,我们使用装饰器解决该问题,首先定义装饰器函数如下:
从装饰器的定义来看,其实就是一个闭包实现,满足了在上篇对闭包三个条件的定义:
1) timer函数内部定义了wrapper函数,满足函数嵌套;
2) 内部函数wrapper使用了外部函数 timer的变量func_name;
3) 返回是一个内部函数的引用;
因此,装饰器本质是函数,是闭包的应用。
现在,我们用装饰器timer实现对func函数所提出的需求,即增加函数耗时测量功能。
使用装饰器的方法如下:
使用上面2步,调用func()时,虽然函数名相同,原func()函数也未做改动,但输出结果已经增加了耗时统计功能。如果不理解,请继续看上篇《理解Python中的闭包》中关于闭包的讲解。
另外,python的装饰器有个更简洁的表示方式,即使用“语法糖”@,如下:
使用装饰器语法糖@的调用方式
四 装饰器的作用
从上文分析,可以了解到,装饰器主要用于为已存在的函数对象附件额外的功能,而原先的函数的内部实现可以不做改动,调用方式也保持不变,而这些附加的功能是可以抽离出来作为共用的,避免了相似场景下代码的冗余。
其他资源分享:
关于装饰器:请参看http://i.youku.com/weiworld521 第21节;
看完本文有收获?请转发分享给更多人
关注 【小蟒社区】,一起学Python
领取专属 10元无门槛券
私享最新 技术干货