Let's say I have a function:
def foo(a=None, b=None, c=None):
return "a:%s, b:%s, c:%s" % (a, b, c)
I have a dictionary with some (or none) of the arguments above, but also with keys that are not named arguments in the function, eg:
d = {'a': 1, 'x': 4, 'b': 2, 'y': 5}
If I call the following I will get an error, because 'x' and 'y' are not keyword arguments in the foo function.
foo(**d) # error
Is there an elegant way of passing the arguments from a dictionary to a function, but only those values with keys that match the function arguments.
Please correct me if my argument/parameter terminology is off.
def foo(a = None, b=None, c=None,**extras):
return "a:%s, b:%s, c:%s" % (a, b, c)
here the **extras
will collect all the extra named/keyword arguments.
@Ashwini Chaudhary has a very pythonic way of solving your problem. However, it requires changing the signature of your foo
function.
If you don't want to change your function signature, you can use introspection to find out what arguments your function expects:
arg_count = foo.func_code.co_argcount
args = foo.func_code.co_varnames[:arg_count]
args_dict = {}
for k, v in d.iteritems():
if k in args:
args_dict[k] = v
foo(**args_dict)
Interesting question. I think that most people in real life use @Ashwini Chaudhary approach.
I do agree with @Rodrigue that there are times you can't modify the call signature of the function (someone else's module perhaps) .
When that happens, Use a function decorator
from inspect import getargspec
from funtools import wraps
def allow_kwargs(foo):
argspec = getargspec(foo)
# if the original allows kwargs then do nothing
if argspec.keywords:
return foo
@wraps(foo)
def newfoo(*args, **kwargs):
#print "newfoo called with args=%r kwargs=%r"%(args,kwargs)
some_args = dict((k,kwargs[k]) for k in argspec.args if k in kwargs)
return foo(*args, **some_args)
return newfoo
# with your function:
@allow_kwargs
def foo(a = None, b=None, c=None):
return "a:%s, b:%s, c:%s " % (a,b,c)
# with someone_elses function:
from some_place import foo
foo = allow_kwargs(foo)
@wraps
from functools keeps the __name__
and __doc__
strings in tact. You could also:
FunctionMaker
from the decorators module but this should be a more reusable approach.
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.