我无法理解 partial
在 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
应该取代 sum2
。 x
和4
是什么关系?
最佳答案
大致来说,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/