Search code examples
pythonpython-3.xfunctionvariable-assignmentwrapper

How to pass **kwargs parameters to the relevant wrapped functions?


I want to define a wrapper function that wraps up a number of other functions with many arguments and want to use the magic variables in the wrapper function.

For example, suppose I have these three functions:

def function1(ret, ben, period=0, **kwargs):
 return ret, ben, period


def function2(ret, ben, risk_free=0, **kwargs):
 return ret, ben, risk_free

def function3(ret, ben, rf=0, **kwargs):
 return ret, ben, rf

And I want to wrap these functions with another function and use the magic variables so I can keep track of all possible arguments that each function might take.

I have tried something like this:

def wrapper_function(ret, ben, **kwargs):

  out1 = function1(ret, ben, **kwargs)
  out2 = function2(ret, ben, **kwargs)
  out3 = function3(ret, ben, **kwargs)

  return out1, out2, out3 

but this obviously fails because let's say, function1 does not have the same arguments as, for example, function2.

For example, if I call the wrapper function with wrapper_function(ret, ben, rf ) it will fail because functions1 and function2 don't have rf as their arguments.

My scope is essential to have a function that does something like this:

def wrapper_function(ret, ben, **kwargs1,**kwargs2,**kwargs3):

  out1 = function1(ret, ben, **kwargs1)
  out2 = function2(ret, ben, **kwargs2)
  out3 = function3(ret, ben, **kwargs3)

  return out1, out2, out3

This does not seem to work in python, however.

Any idea on how to use the magic variable in the wrapper function so no matter what arguments the functions inside it have it would work?


Solution

  • With the help of getfullargspec, You can see what arguments your individual functions need, then get those from kwargs and pass them to the functions.

    def wrapper_function(ret, ben, **kwargs):
        fns = (function1, function2, function3)
        results = []
    
        for fn in fns:
            fn_args = set(getfullargspec(fn).args)
            fn_required_args = fn_args - {'ret', 'ben'}
    
            required_dict = {
                item: kwargs[item] for item in fn_required_args if item in kwargs
            }
            results.append(fn(ret, ben, **required_dict))
    
        return results
    

    Here is a complete code for test:

    from inspect import getfullargspec
    
    
    def function1(ret, ben, period=0):
        return ret, ben, period
    
    
    def function2(ret, ben, risk_free=0):
        return ret, ben, risk_free
    
    
    def function3(ret, ben, rf=0):
        return ret, ben, rf
    
    
    def wrapper_function(ret, ben, **kwargs):
        fns = (function1, function2, function3)
        results = []
    
        for fn in fns:
            fn_args = set(getfullargspec(fn).args)
            fn_required_args = fn_args - {'ret', 'ben'}
    
            required_dict = {
                item: kwargs[item] for item in fn_required_args if item in kwargs
            }
            results.append(fn(ret, ben, **required_dict))
    
        return results
    
    
    print(wrapper_function(10, 20, period=11, risk_free=22))
    

    output:

    [(10, 20, 11), (10, 20, 22), (10, 20, 0)]
    

    note: If you don't want to hardcode this:

    fn_required_args = fn_args - {'ret', 'ben'}
    

    You can get the {'ret', 'ben'} part, from this expression:

    set(getfullargspec(wrapper_function).args)