Reputation: 13
Let there are some codes like
def f(a, b):
# some code (no return)
def g(c, d, e):
# some code (no return)
Then, I want to make a function "merge_functions" which
h = merge_functions(f, g)
works same with:
def h(a, b, c, d, e):
f(a, b)
g(c, d, e)
There could be more or fewer parameters in f and g, and I want to keep the name of the parameters the same.
There is no default value in any parameters.
I have tried:
from inspect import signature
getarg = lambda func: list(dict(signature(func).parameters).keys())
to_arg_form = lambda tup: ', '.join(tup)
def merge_functions(f, g):
fl = getarg(f)
gl = getarg(g)
result = eval(f"lambda {to_arg_form(fl+gl)}:{f.__name__}({to_arg_form(fl)}) and False or {g.__name__}({to_arg_form(gl)})")
return result
However, I could only use this function in the same file, not as a module.
How can I make the function that can also be used as a module?
Upvotes: 0
Views: 378
Reputation: 39354
Ok, so I can make a function which will call the functions passed to it in order with the right number of parameters.
I'm not sure that getting the names of the parameters is possible in the general case: There may be functions you want to compose which have the same parameter names.
from inspect import signature
def merge_functions(*funcs):
def composite(*args):
new_args = args[:]
for f in funcs:
sigs = signature(f).parameters
fargs = new_args[:len(sigs)]
new_args = new_args[len(sigs):]
f(*fargs)
return composite
def f(a, b):
print(f'Inside f({a},{b})')
def g(c, d, e):
print(f'Inside g({c},{d},{e})')
h = merge_functions(f, g)
h(1,2,3,4,5)
Output:
Inside f(1,2)
Inside g(3,4,5)
Upvotes: 1
Reputation: 5096
You can try something like this code which creates a third function which you can use everywhere:
def f1(x1, x2, **args):
print(f"{x1} {x2}")
def f2(x1, x3, x4, **args):
print(f"{x1} {x3} {x4}")
def merge(f1, f2):
return lambda **args: (f1(**args), f2(**args))
f3 = merge(f1, f2)
f3(x1=1, x2=2, x3=3, x4=4)
Upvotes: 1