Search code examples
pythonfunctionkeyword-argument

Master function that executes subfunctions


I have two functions that accept different parametes:

def foo(name, age):
    pass
def bar(color, shape):
    pass

Now, I have a master function that I want to be able to call with the function I want to execute and it's parameters. Since it's a master function that might call either foo or bar, it's called with only two params (the function to be executed and the parameters for this function.

function is a string telling what function to execute

params will be a dictionary of parameters (like **kwargs)

I can do this to make it work:

def master(function, params):
    if function == 'foo':
        foo(params['name'], params['age'])
    elif function == 'bar':
        foo(params['color'], params['shape'])

And then I call master like:

master('foo',{'name': 'John', 'age': 99})

However if master has a lot of subfuntions to call, there's too much conditions and picking the right parameters for each function.

So I basically have two questions:

1) Instead of calling master with the name of the function and then checking this name in a condition, can I directly pass the function to be executed? If so, how do I execute the function then?

Something like calling master like this:

master(foo(), {'name': 'John', 'age': 99})

2) functions foo and bar don't have **kwargs, however it would be very convinient if I can call them passing just a dictionary and then they assign to each variable their corresponding value from the dict.

So basically, could I do:

params = {'name':'John', 'age':99, 'color':red, 'shape':circle}
foo(params)  # I would like to to this even if foo doesn't have **kwargs
bar(params)  # same for bar

So at the end my ideal call of master would be:

params = {'name':'John', 'age':99, 'color':red, 'shape':circle}

master(foo(), params) # to execute foo
master(bar(), params) # to execute bar

Solution

  • You can pass functions as arguments:

    def master(func, arguments: dict):
        if func is foo:
            args = arguments["name"], arguments["age"]
        elif func is bar:
            args = arguments["color"], arguments["shape"]
    
        return func(*args)
    

    This can be done even simpler if you don't know the names of the functions' arguments:

    def master(func, arguments: list):
        return func(*arguments)
    

    A much more generic version is the following:

    def master(function, *positional_arguments, **keyword_arguments):
        function(*positional_arguments, **keyword_arguments)
    
    master(foo, 'John', 56)
    master(foo, **{'name': 'John', 'age': 56})
    master(foo, name='John', age=56)
    master(foo, *['John', 56])