一、装饰器的用途和作用
装饰器,一种高阶函数的表达方法,传入函数,返回函数。
将需要完善的函数作为参数 传入高阶函数,在高阶函数内,调用这个函数,并返回一个函数名,代替待完善函数。
用途:已经定义了函数,想动态改变函数功能,又不想改变原函数的代码时,可以使用装饰器。
装饰器作用:
可以极大地简化代码,避免每个函数编写重复性代码
.Python内置的@语法就是为了简化装饰器调用;
检测性能:@performance
数据库事务:@transaction
URL路由:@post('/register')
二、无参数的decorator
要让 @log 自适应任何参数定义的函数,可以利用Python的 *args 和 **kw,保证任意个数的参数总是能正常调用:
*args可以当作可容纳多个变量组成的tuple
**kw可以当作容纳多个key和value的dict
同时使用*args和**kws时,必须*args参数列要在**kw前
栗子:计算函数调用的时间可以记录调用前后的当前时间戳,然后计算两个时间戳的差。
import time
def performance(f):
def fn(*args,**kw):
t1=time.time()
r=f(*args,**kw)
t2=time.time()
print 'call %s() in %fs'%(f.__name__,(t2-t1))
return r
return fn
@performance
def factorial(n):
return reduce(lambda x,y: x*y, range(1, n+1))
print factorial(10)
三、带参数的decorator
带参数的log函数首先返回一个decorator函数,再让这个decorator函数接收my_func并返回新函数:
栗子:
def log(prefix):
def log_decorator(f):
def wrapper(*args, **kw):
print '[%s] %s()...' % (prefix, f.__name__)
return f(*args, **kw)
return wrapper
return log_decorator
@log('DEBUG')
def test():
pass
print test()
四、完善decorator
由于decorator返回的新函数函数名已经不是原函数,而是@log内部定义的。这对于那些依赖原函数名的代码就会失效。decorator还改变了函数的__doc__等其它属性。如果要让调用者看不出一个函数经过了@decorator的“改造” ,就需要把原函数的一些属性复制到新函数中。
Python内置的functools可以用来自动化完成这个“复制”的任务,@functools.wraps应该作用在返回的新函数上。
最后需要指出,由于我们把原函数签名改成了(*args, **kw),因此,无法获得原函数的原始参数信息。即便我们采用固定参数来装饰只有一个参数的函数。
Python内置的functools可以用来自动化完成这个“复制”的任务,@functools.wraps应该作用在返回的新函数上。
最后需要指出,由于我们把原函数签名改成了(*args, **kw),因此,无法获得原函数的原始参数信息。即便我们采用固定参数来装饰只有一个参数的函数。
栗子:
import functools def log(f): @functools.wraps(f) def wrapper(*args, **kw): print 'call...' return f(*args, **kw) return wrapper
五、偏函数
当一个函数有很多参数时,调用者就需要提供多个参数。如果减少参数个数,就可以简化调用者的负担。
functools.partial可以把一个参数多的函数变成一个参数少的新函数,少的参数需要在创建时指定默认值,这样,新函数调用的难度就降低了。
>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
>>> int2('1010101')
85
>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
>>> int2('1010101')
85