定义函数闭包的 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
.
的定义中交换参数 a
和 b
的顺序
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)
我在模块中定义了一些函数 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
.
a
和 b
的顺序
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)