装饰器:Python的 decorator 本质上就是一个高阶函数,它接收一个函数作为参数,然后,返回一个新函数。
使用 decorator 用Python提供的 @ 语法,这样可以避免手动编写 f = decorate(f) 这样的代码。
编写无参数decorator:
def log(f):
def fn(x):
print 'call ' + f.__name__ + '()...'
return f(x)
return fn
如果先前你已经编写定义了上面的函数,后面需要用到,为避免不必要的重复,可以直接使用装饰器的@语法就可简化。
@log
两者之间是等价的。
但是如果@log需要传入两个或者多个参数,那么可以利用Python的 *args 和 **kw,保证任意个数的参数总是能正常调用:例如:
def log(f):
def fn(*args, **kw):
print 'call ' + f.__name__ + '()...'
return f(*args, **kw)
return fn
编写带参数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()
执行结果:
[DEBUG] test()...
None(注意:因为函数没有return,因此是空即None)
完善decorator:@decorator可以动态实现函数功能的增加,但是,经过@decorator“改造”后的函数,和原函数相比,除了功能多一点外,由decorator返回的新函数函数名已经不是原函数名,而是@log内部定义的返回的函数的名字。
然而,如果想返回的是原函数的名字,那么可以使用Python内置的functools来实现。
import functools
def log(f):
@functools.wraps(f)
def wrapper(*args, **kw):
print 'call...'
return f(*args, **kw)
return wrapper
偏函数:(多多理解)
functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),可以直接使用下面的代码创建一个新的函数int2:
>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
>>> int2('1010101')
85
所以,functools.partial可以把一个参数多的函数变成一个参数少的新函数,少的参数需要在创建时指定默认值,这样,新函数调用的难度就降低了。