粗略地说,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,4),您创建了一个新函数(准确地说,是一个可调用函数),它的行为与sum2类似,但少了一个位置参数。缺少的参数总是被4代替,因此partial(sum2, 4)(2) == sum2(4,2)
至于为什么需要它,有各种各样的情况。举个例子,假设你必须将一个函数传递到有两个参数的地方:
class EventNotifier(object):
def __init__(self):
self._listeners = []
def add_listener(self, callback):
''' callback should accept two positional arguments, event and params '''
self._listeners.append(callback)
# ...
def notify(self, event, *params):
for f in self._listeners:
f(event, params)
但是你已经拥有的函数需要访问第三个context对象来完成它的工作:
def log_event(context, event, params):
context.log_event("Something happened %s, %s", event, params)
因此,有几个解决方案:
自定义对象:
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))
λ:
log_listener = lambda event, params: log_event(context, event, params)
notifier.add_listener(log_listener)
分音:
context = get_context() # whatever
notifier.add_listener(partial(log_event, context))
在这三种方法中,偏微分是最短和最快的。
(对于更复杂的情况,您可能需要一个自定义对象)。