Python中partial函式的工作原理
阿新 • • 發佈:2018-12-30
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方法是最簡潔和最快的。