Python语法糖-装饰器

这里用来记录Python各种甜得发腻的语法糖,以及各种变形用法。

太初,神谕(pythonic),import light,于是有了光。


装饰器是用来给函数增加新功能的,对于支持高阶函数的语言,函数参数直接穿进去就好了。但是Python提供了更为优雅的解决方案,只需要一个@就能搞定。

装饰器函数需要单独写出来,两层,第一层接受一个函数function就可以了,第二层构造一个函数来接受function的参数然后再内部完成需要添加的功能并且正确调用函数,然后在第一层里返回第二层构造的这个函数。例如写好了一个很蛋疼的代码之后想测测时间……

# encoding: utf-8

import time

def timer(function):
    def decorator(*args,**kwargs):
        start=time.time()
        Return=function(*args,**kwargs)
        print 'cost %s'%(time.time()-start)
        return Return
    return decorator

@timer
def mul(row,column):
    for i in xrange(row):
        for j in xrange(column):
            print i,j,i*j

if __name__=='__main__':
    mul(100,100)
运行结果显而易见:

99 96 9504
99 97 9603
99 98 9702
99 99 9801
cost 0.34299993515
这种直接在内部构造函数,然后将函数返回的做法,返回得到的函数具有自己的参数列表,所以也就构成了从内向外展开的结构。

然后就是在这种记忆化用法,最典型的就是那个递归写法的斐波拉契,用装饰器造一个缓存搞搞就行了……

# encoding: utf-8

import time

def memorize(function):
    Return={}
    def decorator(*args):
        if args not in Return:
            print args
            Return[args]=function(*args)
        return Return[args]
    return decorator

@memorize
def fib(n):
    if n==0:
        return 1
    elif n==1:
        return 1
    else:
        return fib(n-1)+fib(n-2)
    
def timer(function):
    def decorator(*args,**kwargs):
        start=time.time()
        Return=function(*args,**kwargs)
        print 'cost %s'%(time.time()-start)
        return Return
    return decorator

@timer
def cal(n):
    return fib(n)

if __name__ == '__main__':
    cal(100)
    cal(100)
可以注意到这几个问题:

  1. 缓存是全局有效的,这个字典会一直存在,以后再次调用也是一样从里面读取数据。这也同样带来一个问题,一个缓存装饰器只能给一个函数用,不然会混淆。
  2. 装饰器是在每次调用这个函数的时候进入,对于测时间这种我只想要一个最后结果的东西,是不是还是需要手动用另外一个函数启动递归然后装饰这个函数?
(未完)

你可能感兴趣的:(Python语法糖-装饰器)