用于定义函数闭包的Pythonic方法

时间:2018-05-17 15:09:44

标签: python function coding-style closures metaprogramming

我在模块mymodule中定义了一些函数:

def f1(a, b):
    # do something with a and b

由于许多设计原因,在主脚本中,我需要从高阶函数f1调用mycaller,该函数只传递a作为参数。另一个参数b仅在主脚本中可用。

在内部,mycaller如下所示:

  def mycaller(list_of_functions, a):
        for f in list_of_functions:
             f(a)

到目前为止,我已经完成了

from mymodule import f1

bb = myB()
aa = myA()

def closure_f1(a):
    return f1(a, bb)

mycaller([closure_f1], aa)

这是设计这种封闭的正确方法吗? 现在我最终在主脚本中出现了许多看起来很难看的闭包,我相信也可能会给序列化带来问题。 我怎样才能改善这个?

以下是我在没有单独的closure_f1函数的情况下进行的一些尝试:

mycaller([f1],a)

然而,该函数错过了b参数。 然后我试过了

mycaller([f1(b)],a)

但当然这会导致函数调用(失败),而不是传递带有参数b的函数。

1 个答案:

答案 0 :(得分:2)

几种可能性:

<强> 1。使用functools.partial

如果你想修复第一个参数(或前几个参数),只需使用functools.partial

from functools import partial
mycaller([partial(f1, bb)], aa)

为了使用您的示例,您必须在a的定义中交换参数bf1的顺序。

<强> 2。定义自己的partial来修复第二个参数

如果你想修复第二个参数,functools.partial没有帮助,因为它从左到右工作。但是如果你有很多函数需要修复第二个参数,你可以这样做:

def partial2(f, y):
  def res(x):
    return f(x, y)
  return res

然后按如下方式使用它:

mycaller([partial2(f1, bb)], aa)

第3。只需使用lambda s:

这有点冗长,但同时也是最灵活的可能性:

mycaller([lambda x: f1(x, bb)], aa)

如果您不想通过一堆简单的函数定义来污染命名空间,那么显式的lambda可能更好。

<强> 4。只需定义帮助函数

在定义辅助函数时,我没有看到任何灾难,特别是如果经常使用它。所以,只需按closure_f1保持原样并使用:

mycaller([closure_f1], aa)