Search code examples
pythonfunctioninheritanceargskeyword-argument

relay multiple keyword arguments from outer function to inner functions in Python?


I am trying to pass arguments to an outer function that then relays them to one or more inner functions. The closest I've come to achieving this:

def multiply(number, factor=1):
    return number*factor

def add(number, to_add=0):
    return number+to_add

def multiply_add(number, *args):
    return add(multiply(number, *args[0]), *args[1])

multiply_add(5, [3], [200])
Out[]: 215

This solution is impractical in a few ways: 1) The user has to know the order in which to pass the arguments, without using keywords; and 2) These arguments have to be iterables for some reason, otherwise get "TypeError: multiply() argument after * must be an iterable, not int".

My question: how to rewrite multiply_add() so the following works? :

multiply_add(5, factor=3, to_add=200)

P.S. I've seen a working example of this with Seaborn calling additional Matplotlib arguments. For example, making the dot size equal to 25:

sns.jointplot(x='A', y='B', data=df, kind='reg', scatter_kws={'s': 25})

Something in this form would be great too.


Solution

  • Ok, I figured out how to do this offline. There are at least two ways.

    FIRST WAY: slap **kwargs absolutely everywhere

    def multiply(number, factor=1, **kwargs):
        return number*factor
    
    def add(number, to_add=0, **kwargs):
        return number+to_add
    
    def multiply_add(number, **kwargs):
        return add(multiply(number, **kwargs), **kwargs)
    
    multiply_add(5, to_add=200, factor=3)
    

    Note that argument order doesn't matter here.

    SECOND WAY: specify different sets of **kwargs and pass them in dict form (my preferred)

    def multiply(number, factor=1):
        return number*factor
    
    def add(number, to_add=0):
        return number+to_add
    
    def multiply_add(number, kwargs_multiply, kwargs_add):
        return add(multiply(number, **kwargs_multiply), **kwargs_add)
    
    multiply_add(5, {'factor':3}, {'to_add':200})
    

    Note that argument order DOES matter here: the multiply() arguments need to be specified before the add() arguments.