我无法了解部分功能在functools中的工作方式。
我有来自here的以下代码:

>>> 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

现在排队
incr = lambda y : sum(1, y)

我知道我传递给incr的任何参数都将作为y传递给lambda,后者将返回sum(1, y)1 + y

我明白那个。但是我不明白这个incr2(4)
4如何作为x在部分函数中传递?对我来说,4应该代替sum2x4有什么关系?

最佳答案

大致而言,partial会执行以下操作(除了关键字args支持等):

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)
至于为什么需要它,有很多情况。仅举一个例子,假设您必须在一个预期有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))

Lambda:
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))

在这三者中,partial是最短和最快的。
(对于更复杂的情况,您可能需要自定义对象)。

关于python - functools部分如何工作?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15331726/

10-11 10:37