Python的functools模块提供了很多有用的功能,其中一个就是偏函数(Partial function)。
partial 这个东西是针对函数起作用的,并且是部分的。装饰器是对函数进行包装,算是对函数的整体进行处理(其实是对输入和输出)。部分的话其实只有对参数进行部分处理了。怎么部分处理的呢?
def partial(func, *args, **keywords):
def newfunc(*fargs, **fkeywords):
newkeywords = keywords.copy()
newkeywords.update(fkeywords)
return func(*args, *fargs, **newkeywords)
newfunc.func = func
newfunc.args = args
newfunc.keywords = keywords
return newfunc
我们一步一步的读:
- 闭包定义了一个新的函数newfunc,有2个参数签名fargs和fkeywords。这个newfunc的函数体很简单,就是把partial函数的参数和newfunc函数的参数合并起来给partial函数的第一个参数func函数执行,返回执行后的结果。
- 把partial函数的参数属性赋值给newfunc
- 返回newfunc
示例:
from functools import partial
def add(x, y, z):
print x, y, z
return x + y + z
add1 = partial(add, 10)
print(add1(20, 30))
输出:
10 20 30
60
分部解释:
- partial函数的参数:func=add,args=(10, 20)
- 通过获得partial的返回值:a1 = partial(add, 10, 20)。把返回的newfunc赋值给了a1,则执行a1(30) 与 add(*(10, 20), 30)等价。
复杂的示例说明:
如果我的partial函数第二值传的是个函数,会发生什么事情呢?看如下示例。
def sub(x, y):
return x - y
def div(x, y):
return x/y
def attach_wrap(func1, func2=None):
if func2 is None:
return partial(attach_wrap, func1)
setattr(func1, func2.__name__, func2)
return func1
sub1 = attach_wrap(sub)
print(sub1)
sub2 = sub1(div)
print(sub2)
print(sub2(20, 10)) //10
print(sub2.div(20, 10)) //2.0
解释说明:
attach_wrap(sub)执行,发现func2为None,所以执行if语句: partial(attach_wrap, func1)的返回相当于:
sub1 = attach_wrap(*(func1), *fargs, **fkwargs)
调用sub1(div),这时候func2为div函数,所以把func2设置为func1的属性
返回func1,结果就是func1绑定了func2函数
上面的这种写法经常可以用来在一个函数上绑定另一个函数:
def sub(x, y):
return x - y
def attach_wrap(func1, func2=None):
if func2 is None:
return partial(attach_wrap, func1)
setattr(func1, func2.__name__, func2)
return func1
@attach_wrap(sub)
def div(x, y):
return x/y
print(sub(10, 5))
print(sub.div(10, 5))
网友评论