functools partial 如何完成它的工作? [英] How does functools partial do what it does?

查看:21
本文介绍了functools partial 如何完成它的工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法理解 functools 中的部分是如何工作的.我在这里有以下代码:

<预><代码>>>>总和 = lambda x, y : x + y>>>总和(1, 2)3>>>incr = lambda y : sum(1, y)>>>增量(2)3>>>def sum2(x, y):返回 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 应该取代 sum2.x4 是什么关系?

解决方案

粗略地说,partial 做了这样的事情(除了关键字 args 支持等):

def partial(func, *part_args):定义包装器(*extra_args):args = 列表(part_args)args.extend(extra_args)返回函数(*参数)返回包装器

因此,通过调用 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):''' 回调应该接受两个位置参数,事件和参数 '''self._listeners.append(回调)# ...定义通知(自我,事件,*参数):对于 self._listeners 中的 f:f(事件,参数)

但是你已经拥有的函数需要访问第三个 context 对象才能完成它的工作:

def log_event(context, event, params):context.log_event("发生了 %s, %s", event, params)

所以,有几种解决方案:

自定义对象:

类监听器(对象):def __init__(self, context):self._context = 上下文def __call__(self, event, params):self._context.log_event("发生了 %s, %s", event, params)notifier.add_listener(监听器(上下文))

Lambda:

log_listener = lambda 事件,参数:log_event(context, event, params)notifier.add_listener(log_listener)

带有分音:

context = get_context() # 随便notifier.add_listener(部分(日志事件,上下文))

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

I am not able to get my head on how the partial works in functools. I have the following code from 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

Now in the line

incr = lambda y : sum(1, y)

I get that whatever argument I pass to incr it will be passed as y to lambda which will return sum(1, y) i.e 1 + y.

I understand that. But I didn't understand this incr2(4).

How does the 4 gets passed as x in partial function? To me, 4 should replace the sum2. What is the relation between x and 4?

解决方案

Roughly, partial does something like this (apart from keyword args support etc):

def partial(func, *part_args):
    def wrapper(*extra_args):
        args = list(part_args)
        args.extend(extra_args)
        return func(*args)

    return wrapper

So, by calling partial(sum2, 4) you create a new function (a callable, to be precise) that behaves like sum2, but has one positional argument less. That missing argument is always substituted by 4, so that partial(sum2, 4)(2) == sum2(4, 2)

As for why it's needed, there's a variety of cases. Just for one, suppose you have to pass a function somewhere where it's expected to have 2 arguments:

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)

But a function you already have needs access to some third context object to do its job:

def log_event(context, event, params):
    context.log_event("Something happened %s, %s", event, params)

So, there are several solutions:

A custom object:

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)

With partials:

context = get_context()  # whatever
notifier.add_listener(partial(log_event, context))

Of those three, partial is the shortest and the fastest. (For a more complex case you might want a custom object though).

这篇关于functools partial 如何完成它的工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆