On Fri, Jul 20, 2018 at 7:03 PM, Peter O'Connor <peter.ed.ocon...@gmail.com> wrote: > Often when programming I run into a situation where it would be nice to have > "deferred defaults". Here is an example of what I mean: > > def subfunction_1(a=2, b=3, c=4): > return a+b*c > > def subfunction_2(d=5, e=6, f=7): > return d*e+f > > def main_function(a=2, b=3, c=4, d=5, e=6, f=7): > return subfunction_1(a=a, b=b, c=c) + subfunction_2(d=d, e=e, f=f) > > Here you can see that I had to redefine the defaults in the main_function. > In larger codebases, I find bugs often arise because defaults are defined in > multiple places, and somebody changes them in a lower-level function but > fails to realize that they are still defined differently in a higher > function. > > The only way I currently see to achieve this is not very nice at all, and > completely obfuscates the signature of the function: > > def main_function(**kwargs): > return subfunction_1(**{k: v for k, v in kwargs.items() if k in > ['a', 'b', 'c']}) > + subfunction_2(**{k: v for k, v in kwargs.items() if k in > ['d', 'e', 'f']})
Hmm. This might be something where a bit of a helper could, well, help. Is this a pattern that you make use of a lot? Suppose you write your main function like this: @combines(subfunction_1, subfunction_2) def main_function(sf1, sf2): return subfunction_1(**sf1) + subfunction_2(**sf2) or even like this: @precombine def main_function(subfunction_1, subfunction_2): return subfunction_1 + subfunction_2 The decorator could then generate a new function, with a proper signature (available to help()), that hides the messy details of filtering kwargs - and in the case of precombine, actually calls the function as well. (Obviously you can't use this if you might want to call a subfunction conditionally.) Another option would be to have all your subfunctions absorb and ignore all unexpected arguments. def subfunction_1(a=2, b=3, c=4, **_): return a+b*c def subfunction_2(d=5, e=6, f=7, **_): return d*e+f def main_function(**kw): return subfunction_1(**kw) + subfunction_2(**kw) This doesn't help with the signature, but it's an easy thing to do. You'd have to document your parameters separately from your functions; appropriate for something like the subprocess module (where a bunch of functions basically pipe their args straight into Popen), not appropriate for a lot of other places. On the plus side, both of these ideas work with existing Python versions, so you wouldn't have to wait for 3.8 or 3.9 :) ChrisA _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/