Home > front end >  How to pass **kwargs parameters to the relevant wrapped functions?
How to pass **kwargs parameters to the relevant wrapped functions?

Time:05-03

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?

CodePudding user response:

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)

CodePudding user response:

If I understand the question correctly, you can just pick the relevant arguments out from the kwargs dict:

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

    out1 = function1(ret, ben, kwargs['period'])
    out2 = function2(ret, ben, kwargs['risk_free'])

Of course, you may want to first check if they actually exist in the kwargs, e.g.

period = kwargs['period'] if 'period' in kwargs else 0

CodePudding user response:

Actually, there is a way via introspection (the inspect module). Rough sketch below:

import inspect

def wrapper(ret, ben, **kwargs):
    fun1_argnames = inspect.getargspec(function1).args  # get valid args for function1
    theargs = {key: kwargs[key] for key in fun1_argnames}
    function1(**theargs)

However, this is getting a bit into 'hack' territory. I have never needed such a trick. I have a feeling that your problem could probably be solved in a different way (i.e. do you really need to wrap a huge amount of different functions with a huge amount of different arguments?)

CodePudding user response:

This may be useful:

function1(ret, ben, kwargs.get('period'))
...
  • Related