python装饰器理解

python装饰器,一个强大实用的设计模式!

首先感谢团队的Leno、Damon、以及Joel,是他们让我接触到这个实用的知识点!装饰器是一个著名的设计模式,常用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。

比如:要查看一段程序的执行时间:以往我会在代码前后加入starTime 、endTime来处理;后来觉得在每段代码的前后加代码显得重复累赘,于是创建了一个时间器函数如:timeIt(fn),再将要查看程序执行时间的那段代码也包装成函数,然后将它与参数的形式传递给timeIt()

在相当长的一段时间内,我以为自己这样处理算得上是一个创举,起码一个函数就可以搞定,而不用在每段要检测的代码前后重复插入了吧!直到前些日子项目要求,Leno、Damon向我提到勾子函数与装饰器,才知道有更科学高效的方法进行事务处理!同时感谢Joel,曾经向他讨教过如何有效记录系统运行时间问题时,是他向我道出这个“装饰模式”这个设计模式!那么是如何做的呢?

对于查看运行时间,原来我的思路是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import  time

def sayHi ( ):
     print  "hello world!"

def  timeit (fn ):
    startTime  =  time. time ( )
    fn ( )
    endTime  =  time. time ( )
     print endTime - startTime

timeit (sayHi )

  ;

原来的sayHi()被修改成timeit(saiHi),sayHi作为参数传递了。
那么,装饰模式的思路是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import  time

def  timeit (fn ):
     def wraper ( ):
        startTime  =  time. time ( )
        fn ( )
        endTime  =  time. time ( )
         print endTime - startTime
     return wraper

def sayHi ( ):
     print  "hello world!"

sayHi =  timeit (sayHi )
sayHi ( )

在sayHi()前加入sayHi = timeit(sayHi),进行计时处理,但timeit(sayHi)并不是直接产生调用效果,而是返回一个函数赋值给sayHi! sayHi()调用并没有像我原先的思路那样被修改了,可此sayHi()已非彼sayHi()。
这种在某段代码的前后需要加入一点额外的处理时,这种编程方式被称为面向切面的编程(AOP),而对于什么是装饰器,什么是面向切面编程可以阅读下面这篇好文章:

Python装饰器学习 :http://blog.csdn.net/thy38/article/details/4471421

Python装饰器与面向切面编程:http://www.cnblogs.com/huxi/archive/2011/03/01/1967600.html
如果你还没有阅读《Python装饰器与面向切面编程》,那么你一定也认为在sayHi()前加入的这句 sayHi = timeit(sayHi) 已经是无可挑剔了!其实,它还是可以再优化的!这就是我的队友Leon提到的勾子函数!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import  time

def  timeit (fn ):
     def wraper ( ):
        startTime  =  time. time ( )
        fn ( )
        endTime  =  time. time ( )
         print endTime - startTime
     return wraper

@ timeit
def sayHi ( ):
     print  "hello world!"

sayHi ( )

看到了吧?仅仅是在def saiHi()前增加一句@timeit,它却等同于sayHi = timeit(sayHi)

你可能感兴趣的:(python)