Skip to content Skip to sidebar Skip to footer

Expand Only The Key-value Pairs Required By A Function

Let's say we have a function that takes some arguments and a dict that is a superset of values required to invoke the function: d = {'a': 1, 'b': 2, 'c': 3} def foo(a, b): prin

Solution 1:

Instead of doing this:

deffoo(a, b):
   print(a, b)

You could do this:

deffoo(a, b, **kwargs):
   print(a, b)

Then the function would just ignore all the unneeded arguments.

However, in my view, there are some problems with this approach.

  1. Sometimes you don't own the source code of the function. Of course, you can make lots of wrapper functions. If you do that manually, you'll have to change the signatures of your helper functions every time the library authors modify the function signature.

  2. This solution can make some bugs harder to find. Maybe it's better to explicitly state that you're only using some of the elements from the dictionary.

You can still make it easier using the inspect module of the standard library.

a) Make a decorator that makes the function filter its keyword arguments.

For instance:

import inspect

deffilter_kwargs(f):
  arg_names = inspect.getargspec(f).args
  def_f(*args, **kwargs):
    return f(*args, **{k: v for k, v in kwargs.items() if k in arg_names})
  return _f

# Use it like this:
filter_kwargs(foo)(a_dict)

b) You can create a function that transforms the argument to fit the function

deffit_for(f, kwargs):
  arg_names = inspect.getargspec(f).args
  return {k: v for k, v in kwargs.items() if k in arg_names}

foo(fit_for(foo, a_dict))

Optionally, you can expand this function to also take into account the *args and **kwargs in the original function.


If this is a recurring pattern in your code, you can just pass the dict as a single argument.

Also, as @chepner pointed out in the comments, consider creating a class.

Solution 2:

you could use keyword arguments:

deffoo(**kwarg):
    print(kwarg['a'], kwarg['b'])

foo(**d)

output:

1 2

Solution 3:

Assuming you do not want to modify foo's function signature, you can use foo.__code__.co_varnames to get the argument names of fooif you are using cpython

foo(**{k: d[k] for k in  foo.__code__.co_varnames})

Solution 4:

You can do something like:

d = {"a": 1, "b": 2, "c": 3}
deffoo(a, b, *arg, **kwarg):
    print(a, b)

foo(**d)

Post a Comment for "Expand Only The Key-value Pairs Required By A Function"