Python 使调用者使用functools.partial还是调用工厂函数?

Python 使调用者使用functools.partial还是调用工厂函数?,python,Python,我读过几个比较partial和lambda的参数,但大多数都谈到了partial如何更灵活(不限于表达式),并给出了包装函数的相关信息。但我想从来电者的角度考虑这个问题。这是我的情况 我有一个函数,它接受一个单参数修饰符函数。请求被传递到要修改的修饰符函数中: def my_func(request, modifier): modifier(request) 我还构建了一些实用程序,可以更轻松地创建参数化修改器函数,例如,向请求添加/修改URL参数。我想了两种方法,但不确定哪一种更好 选择

我读过几个比较
partial
lambda
的参数,但大多数都谈到了
partial
如何更灵活(不限于表达式),并给出了包装函数的相关信息。但我想从来电者的角度考虑这个问题。这是我的情况

我有一个函数,它接受一个单参数修饰符函数。请求被传递到要修改的修饰符函数中:

def my_func(request, modifier):
  modifier(request)
我还构建了一些实用程序,可以更轻松地创建参数化修改器函数,例如,向请求添加/修改URL参数。我想了两种方法,但不确定哪一种更好

选择1 这样,调用方可以使用
functools.partial
绑定
参数,如下所示:

modifier = functools.partial(add_params, params={'abc':'123'})
modifier = add_params({'abc':'123'})
选择2 然后呼叫者会这样使用它:

modifier = functools.partial(add_params, params={'abc':'123'})
modifier = add_params({'abc':'123'})
问题:
如果我不关心函数内省,那么使用选项2有什么缺点吗?选项2是否会遇到后期绑定问题?(尽管我的用例没有遇到这种情况)。我非常喜欢选项2更易于调用方使用的方式。

从数学角度来看,这两个函数完全同构(尽管它们的效率可能不同):

出于您的目的,我认为选项2提供了最大的便利性,因为该函数已经实现,因此您不仅可以避免
partial
,还可以轻松地组合它们:

import functools
def compose(*fs):
  return functools.reduce(lambda f, g: lambda x: f(g(x)), fs)

modifier = compose(add_params({'abc':'123'}),
                   add_params({'def':'456'}))
如果您想要直接调用函数,您始终可以执行以下操作:

add_params({'abc':'123'})(request)
与方案1相比,这并不是全部:

add_params(request, {'abc':'123'})
除非您使用函数外部的变量,否则后期绑定不应该造成问题,如果您使用了,总会有办法解决这个问题

不幸的是,选项2的缺点是定义起来很烦人,但这可以通过使用装饰器来简化:

def curry_request(f):
  def wrapper(*args, **kwargs):
    def inner(request):
      f(request, *args, **kwargs)
    return inner
  return wrapper

@curry_request
def add_params(request, params):
  # do something
与部分函数实现代码相比,您的选项2也很好,我认为它在您的情况下没有任何缺点。但是functools.partial是一种常见的简化签名的方法,
如果您想为另一个函数返回一个新的分部函数,您仍然可以调用分部函数。如果您想使用选项2模型,您可能需要实现一个新函数

,感谢您指出了关于
分部更可重用的部分。感谢您的解释。我的首要任务是让调用者更容易使用这些修饰符,所以定义中有点冗长是可以的。
def curry_request(f):
  def wrapper(*args, **kwargs):
    def inner(request):
      f(request, *args, **kwargs)
    return inner
  return wrapper

@curry_request
def add_params(request, params):
  # do something
def partial(func, *args, **keywords):
    def newfunc(*fargs, **fkeywords):
        newkeywords = keywords.copy()
        newkeywords.update(fkeywords)
        return func(*(args + fargs), **newkeywords)
    newfunc.func = func
    newfunc.args = args
    newfunc.keywords = keywords
    return newfunc