python - functools partial 是如何做到的?

我无法理解 partialfunctools 中的工作原理。 我有来自 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 会做这样的事情(除了关键字参数支持等):

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 是最短和最快的。 (对于更复杂的情况,您可能需要自定义对象)。

https://stackoverflow.com/questions/15331726/

相关文章:

python - 我如何捕捉一个像异常一样的 numpy 警告(不仅仅是为了测试)?

python - 类型错误 : Missing 1 required positional argu

python - 为什么 apt-get 功能在 Mac OS X v10.9 (Mavericks

linux - 如何删除 CLOSE_WAIT 套接字连接

python - 什么是字典 View 对象?

linux - 如何在 linux bash/shell 中对图像进行 base64 编码

linux - 使用 bash 历史记录获取先前的命令,复制它,然后 'run' 它但命令注释

linux - 在 printf 中使用颜色

linux - 我可以在已编译的二进制文件中更改 'rpath' 吗?

linux - Git 和硬链接(hard link)