I’ve been a diehard functional programmer for the better part of 10 years. Before I took up Python in 2011, I had been programming in Mathematica for about 4 years, and it left a strong impact on how I think about code. I generally write small scripts and, on rare occasion, modest (~800 lines) frameworks that process data and/or do something mathy. I take pride in minimizing redundancy of my code without seriously impacting readability. I have spent the last three months working on an R&D project at work focused on monitoring machine learning models in production, and sending alerts when things seem off. Among the artifacts I’ll be providing the company from my work is a fully documented Python library for calculating statistical [divergences](https://en.wikipedia.org/wiki/Divergence_(statistics). While this project has probably been the highlight of my last 5 working years, I’ll save a rant about it for another post.

So where was I? Oh right! Die hard funcional programmer! Right, so as a functional programmer, I naturally structured my divergence library around a handful functions that compose in different ways. The functions I defined are fairly general, and necessarily have a bunch of optional arguments to override defaults. For example, some train neural networks, some control the data sampling process during trainng and validation, some control neural network hyperparameters, etc. A large number of them are fed into one big function. We’ll call this F.

def F(..., a=..., b=..., c=...):
    return G(..., a) * H(..., b) * K(..., c))

This obviously isn’t the code itself, but it’s a good illustration of the situation. I want the user to be able to change the default arguments of G, H, and K. To do this, I have to keep adding them as arguments to F with some default parameters. This process works alright, but it can be tedeous to keep refactoring F every time G or H change. Basically, you have to change everything twice. And yes, I really do want G and H separate because it’s useful to be able to replace them with different functions to create new versions of F. Let’s just assume I’ve thought out the breakdown well enough that this is probably the optimal structure for minimal redundancy.

A smart friend suggested having F just take a **kwargs that includes everything that could ever be passed to G, H, and K, and then have those respective functions ignore irrelavent kwargs. This is slick and actually fits my situation because the few arguments shared between G, H, and K really should be the same! Aside from potential scaling issues (do I really want everyone working on this project to have to coordinate naming conventions based on how functions are composed?), this trick only works if G, H, and K all take **kwargs in their function head so they can ignore unneeded **kwargs.

There actually is an efficient solution to this problem.

class F:
    G_defaults = {}
    H_defaults = {}
    K_defaults = {}
    
    def __init__(self, **kwargs):
        self.kwargs = kwargs
        for name, new_kwargs in kwargs.items():
            if hasattr(self, name):
                self.__getattr__(name).update(new_kwargs)

    def __call__(self, *args, **kwargs):
        if kwargs:
            return self.__class__(**self.kwargs).__init__(**kwargs)(*args)
        return G(..., **self.G_defaults) * H(..., **self.H_defaults) * K(..., **self.K_defaults))

Now I can initialize F with separate **kwargs directed at each function it will call and efficiently encode defaults! Note this isn’t quite inheritence because inheritence would override one or more of G_defaults, H_defaults, and K_defaults. Inheritance wouldn’t be bad, but we can do one better with a nicely crafted __init__ function. Now I can specify exactly what’s different in the default arguments and never have to worry about naming conflicts.