定义函数闭包的 Pythonic 方式

Pythonic way to define function closures

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

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

出于多种设计原因,在主脚本中我需要从高阶函数 mycaller 调用 f1,它只会将 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.使用 functools.partial

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

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

为了使此与您的示例一起使用,您必须在 f1.

的定义中交换参数 ab 的顺序

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

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

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

然后按如下方式使用:

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

3。只需使用 lambdas:

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

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

如果您不想被一堆琐碎的函数定义污染命名空间,那么显式 lambda 可能更可取。

4。只需定义一个辅助函数

我不认为定义辅助函数有什么灾难性的,尤其是当它经常被使用时。因此,只需保持 closure_f1 不变并使用:

mycaller([closure_f1], aa)