How to call a function with a dictionary that contains more items than the function has parameters? How to call a function with a dictionary that contains more items than the function has parameters? python python

How to call a function with a dictionary that contains more items than the function has parameters?


How about making a decorator that would filter allowed keyword arguments only:

import inspectdef get_input_names(function):    '''get arguments names from function'''    return inspect.getargspec(function)[0]def filter_dict(dict_,keys):    return {k:dict_[k] for k in keys}def filter_kwargs(func):   def func_wrapper(**kwargs):       return func(**filter_dict(kwargs, get_input_names(func)))   return func_wrapper@filter_kwargsdef foo(a,b):    return a + bd = {'a':1,     'b':2,     'c':3}print(foo(**d))

What is nice about this decorator is that it is generic and reusable. And you would not need to change the way you call and use your target functions.


All of these answers are wrong.

It is not possible to do what you are asking, because the function might be declared like this:

def foo(**kwargs):    a = kwargs.pop('a')    b = kwargs.pop('b')    if kwargs:        raise TypeError('Unexpected arguments: %r' % kwargs)

Now, why on earth would anyone write that?

Because they don't know all of the arguments ahead of time. Here's a more realistic case:

def __init__(self, **kwargs):    for name in self.known_arguments():        value = kwargs.pop(name, default)        self.do_something(name, value)    super().__init__(**kwargs)  # The superclass does not take any arguments

And here is some real-world code which actually does this.

You might ask why we need the last line. Why pass arguments to a superclass that doesn't take any? Cooperative multiple inheritance. If my class gets an argument it does not recognize, it should not swallow that argument, nor should it error out. It should pass the argument up the chain so that another class I might not know about can handle it. And if nobody handles it, then object.__init__() will provide an appropriate error message. Unfortunately, the other answers will not handle that gracefully. They will see **kwargs and either pass no arguments or pass all of them, which are both incorrect.

The bottom line: There is no general way to discover whether a function call is legal without actually making that function call. inspect is a crude approximation, and entirely falls apart in the face of variadic functions. Variadic does not mean "pass whatever you like"; it means "the rules are too complex to express in a signature." As a result, while it may be possible in many cases to do what you're trying to do, there will always be situations where there is no correct answer.


Your problem lies with the way you defined your function, it should be defined like this -

def foo(**kwargs):

And then inside the function you can iterate over the number of arguments sent to the function like so -

if kwargs is not None:        for key, value in kwargs.iteritems():                do something

You can find more info about using **kwargs in this post - http://pythontips.com/2013/08/04/args-and-kwargs-in-python-explained/