partial的代码示例:
>>> sum = lambda x, y : x + y
>>> sum(1, 2)
3
>>> incr = lambda y : sum(1, y)
>>> incr(2)
3
>>> def sum2(x, y):
return x + y
>>> incr2 = functools.partial(sum2, 1)
>>> incr2(4)
5
大体上来讲,partial的功能可以表示成下边的形式:
def partial(func, *part_args):
def wrapper(*extra_args):
args = list(part_args)
args.extend(extra_args)
return func(*args)
return wrapper
因此,当调用partial(sum2, 1)时,实际上创建了一个类似sum2的新函数,不同之处是少了一个参数。传入的参数默认被1代替,也就是partial(sum2, 1)(4) == sum2(1, 4)
这种特殊的方式有许多的应用场景。这里举一个例子,假如你想在某个地方传递一个函数,并且,期望这个函数的参数是2个:
class EventNotifier(object):
def __init__(self):
self._listeners = []
def add_listener(self, callback):
''' callback 接收两个参数, event 和 params '''
self._listeners.append(callback)
# ...
def notify(self, event, *params):
for f in self._listeners:
f(event, params)
但是在某种情形下,在add_listener的callback函数中你需要接收第三个参数–context对象:
def log_event(context, event, params):
context.log_event("Something happened %s, %s", event, params)
这里有几种解决方案:
1.创建一个特定的对象处理:
class Listener(object):
def __init__(self, context):
self._context = context
def __call__(self, event, params):
self._context.log_event("Something happened %s, %s", event, params)
notifier.add_listener(Listener(context))
2.Lambda方案:
log_listener = lambda event, params: log_event(context, event, params)
notifier.add_listener(log_listener)
3.partials方案:
context = get_context() # whatever
notifier.add_listener(partial(log_event, context))
在上面的三种方案中,partial方法是最简洁和最快的。
[1]https://stackoverflow.com/questions/15331726/how-does-the-functools-partial-work-in-python