简体   繁体   中英

Dictionary unpacking into function when parameters are incompatible

I'm not sure that it's possible, I would like to unpack dictionary into function but I haven't similar parameters. Is it possible to easily restrict a dictionary to a subset?

def foo(a=0, b=0, c=0):
    print("a=%s, b=%s, c=%s"%(a,b,c))

my_dict = {'a':10, 'b':20, 'd':40}
foo(**my_dict)

Output

TypeError                                 Traceback (most recent call last)
<ipython-input-1-d40731664736> in <module>()
      3 
      4 my_dict = {'a':10, 'b':20, 'd':40}
----> 5 foo(**my_dict)

TypeError: foo() got an unexpected keyword argument 'd'

And I want to obtain

a=10, b=20, c=0

result where 'd' is automatically rejected.

It's just an example. In my case the function is not mine, I cannot redefined her parameters, foo is unmodifiable.

I have many functions in similar case as foo() and these functions are object's methods.

Any ideas?

Inspecting the function signature will help:

import inspect

params = inspect.signature(foo).parameters.keys()

foo(**{k: v for k, v in my_dict.items() if k in params})

Here is a (hopefully) correct solution using inspect . Since the parameter list returned by inspect may contain star args and also positional only args, it is not enough to just compare the names.

import inspect

def filter_kwds(f, kwds):
    params = inspect.signature(f).parameters
    if any(p.kind == inspect.Parameter.VAR_KEYWORD for p in params.values()):
        return kwds
    else:
        return {k:kwds[k] for k, v in params.items()
                if k in kwds and v.kind in (inspect.Parameter.KEYWORD_ONLY,
                                            inspect.Parameter.POSITIONAL_OR_KEYWORD)}

def f(a, *b, c=4):
    pass

def g(a, *b, c=4, **d):
    pass

print(filter_kwds(f, dict(a=1, b=2, d=4)))
print(filter_kwds(g, dict(a=1, b=2, d=4)))

Output:

{'a': 1}
{'a': 1, 'b': 2, 'd': 4}

Note that the function in the first example omits the name of the star arg, and in the second example detects the presence of a double star arg and therefore does no filtering

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM