I have some function defined in a module mymodule
:
def f1(a, b):
# do something with a and b
For a number of design reasons, in the main script I need to call f1
from a higher-order function mycaller
, which will only pass a
as an argument. The other parameter b
is only available in the main script.
Internally, mycaller
looks as follows:
def mycaller(list_of_functions, a):
for f in list_of_functions:
f(a)
So far, I have done
from mymodule import f1
bb = myB()
aa = myA()
def closure_f1(a):
return f1(a, bb)
mycaller([closure_f1], aa)
Is this the correct way of designing such a closure? Right now I end up with many closures in main script which looks ugly and I believe might also give problems with serialization. How can I improve this?
Here are some attempts that I made without a separate closure_f1
function:
mycaller([f1],a)
However, then the function misses the b argument. Then I have tried
mycaller([f1(b)],a)
but of course this lead to a function call (which fails) rather than in passing the function with argument b
set.
Several possibilities:
1. Use functools.partial
If you want to fix the first argument (or first few arguments), just use functools.partial
:
from functools import partial
mycaller([partial(f1, bb)], aa)
For this to work with your example you would have to swap the order of arguments a
and b
in the definition of f1
.
2. Define your own partial
that fixes the second argument
If you want to fix the second argument, the functools.partial
doesn't help, because it works from left to right. But if you have a lot of functions where you have to fix the second argument, you could do something like this:
def partial2(f, y):
def res(x):
return f(x, y)
return res
and then use it as follows:
mycaller([partial2(f1, bb)], aa)
3. Just use lambda
s:
This is a somewhat verbose, but at the same time the most flexible possibility:
mycaller([lambda x: f1(x, bb)], aa)
An explicit lambda could be preferable if you don't want to pollute the namespace by a bunch of trivial function definitions.
4. Just define a helper function
I don't see anything catastrophic in defining a helper function, especially if it is used often. So, just leave closure_f1
as-is and use:
mycaller([closure_f1], aa)