Reputation: 17680
Support I have defined some functions, e.g. (very simplified example)
def f1(a, b, arg='something'):
...
def f2(c, arg='else'):
...
Then I call use them as:
def f(a, b, c):
return f1(a, b) + f2(c)
Since this is very commonly used, but I want to have f1
and f2
defined separately so that it is possible to call just one.
I want to have the possibility when calling f
to call f1
and f2
with different default arguments, so I can do:
def f(a, b, c, arg1='something', arg2='else'):
return f1(a, b, arg1) + f2(c, arg2)
This is not very maitanable (I have many more functions than 2 and many more arguments), since when I update one function I need to update f
.
One options would be to use None
as default values and then change them inside the body of the functions, e.g.
def f1(a, b, arg=None):
arg = arg or 'something'
...
but this hides the real value of the default argument from the signature.
In addition this doesn't solve all my problems since if I add one new argument to f1
I have to change the signature of f
and also its implementation...
Upvotes: 2
Views: 184
Reputation: 221
Use None (or sentinel, if None is actually a meaningful value) as a default value and then set the "real" default value inside the function.
Example
def f1(a, b, arg=None):
arg = arg or 'something'
...
def f2(c, arg=None):
arg = arg or 'else'
...
def f(a, b, c, arg1=None, arg2=None):
return f1(a, b, arg1) + f2(c, arg2)
This way, if a parametr is not specified, the default value will propagate up the calling tree.
Upvotes: 0
Reputation: 1527
def f1(a, b, arg='something', **kwargs):
pass
def f2(c, arg='else', **kwargs):
pass
def f(a, b, c, arg1='something', arg2='else'):
kwargs = locals()
return f1(**kwargs) + f2(**kwargs)
If you want something from both worlds namely dynamic delegation and static definitions this is the most simple solution but it's not ideal:
**kwargs
to functions so they don't fail when too many arguments are passed;c
in f2
to b
.If you have many fn
functions the return
line may end up like this:
return sum(f(**kwargs) for f in (f1, f2, ..., fn))
Upvotes: 0
Reputation: 339
Try using this function!
def f(a, b, c, *args):
if len(args)==2:
return(f1(a, b, args[0]) + f2(c, args[1]))
else:
return(f1(a, b, None) + f2(c, None))
Upvotes: 0
Reputation: 4265
It sounds like you are getting to the point where object oriented programming can help you. You could rewrite your functions as a class:
class FFuncs:
def __init__(self, a, b, c, arg1="foo", arg2="bar"):
self.a = a
self.b = b
self.c = c
self.arg1 = arg1
self.arg2 = arg2
def f1(self):
return str(self.a + self.b) + self.arg1
def f2(self):
return str(self.c) + self.arg2
def f(self):
return self.f1() + self.f2()
FFuncs(2, 3, 5, arg1=" Foos and ", arg2=" Spam").f()
# Returns "5 Foos and 5 Spam"
Now you always have access to the default values of your kwargs before each execution. And as mentioned in the comments, if you need an especially flexible call signature for any given method of your class, you can still abstract away with *args, **kwargs
.
Upvotes: 1