这里用来记录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)
可以注意到这几个问题:
- 缓存是全局有效的,这个字典会一直存在,以后再次调用也是一样从里面读取数据。这也同样带来一个问题,一个缓存装饰器只能给一个函数用,不然会混淆。
- 装饰器是在每次调用这个函数的时候进入,对于测时间这种我只想要一个最后结果的东西,是不是还是需要手动用另外一个函数启动递归然后装饰这个函数?