1. 程式人生 > >Python中partial函式的工作原理

Python中partial函式的工作原理

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方法是最簡潔和最快的。