How to pass dict members to a function

Suppose I have a function that I don't control looks something like this:

def some_func(foo, bar, bas, baz): do_something() return some_val 

Now I want to call this function by passing elements from a dict that contains keys that are identical to the arguments to this function. I could do something like:

 some_func(foo=mydict['foo'], bar=mydict['bar'], bas=mydict['bas'], baz=mydict['baz']) 

Is there some elegant way that I could take advantage of the fact that the keys match the pairs in order to do this in less detail? I know that I can pass the entire dict, but let me say that I either do not want or cannot change the function to accept a single dict, and not separate arguments.

Thanks Jerry

+4
source share
2 answers

What is the decompression of arguments ** intended for:

 some_func(**mydict) 

See also Unpacking argument lists in a Python tutorial.

+11
source

As Sven points out, you can pass dict functions using unpacking ** . But if the dict contains keys that are not the argument names of the target function, this only works if the function you are calling takes the keyword arguments using ** notation. If this is not the case, you will receive an error message.

If the function you are calling does not have the **kwargs parameter, the easiest way to handle it is to add it. But if you cannot do this, you have a couple of approaches:

1) Write a wrapper function:

 def wrapper(foo, bar, baz, quux, **kwargs): return some_func(foo, bar, baz, quux) wrapper(**mydict) 

2) Write a function to extract only the necessary keys:

 def extract(dikt, keys): return dict((k, dikt[k]) for k in keys.split()) some_func(**extract(mydict, "foo bar baz quux")) 

3) Write a function that examines the function you are calling and extracts the words you need from the dictionary โ€” basically the same as # 2, except that you don't need to โ€œrepeat yourselfโ€ the same way.

 def call_with_dict(func, dikt): func(**dict((k, dikt[k]) for k in func.func_code.co_varnames[:func.func_code.co_argcount])) call_with_dict(some_func, my_dict) 

Note that this prevents you from skipping arguments that have default values โ€‹โ€‹in the function signature. You could do extra introspection to allow (the length of func.func_defaults determines which of the arguments has default values).

This introspection for Python 2.x, Python 3 and later is likely to require some tweaking. For this reason, I prefer one of the first two methods.

PS - Thanks to Sven for catching my missing ** in my second approach.

+5
source

Source: https://habr.com/ru/post/1398247/


All Articles