假设我有一个功能:
def foo(a=None, b=None, c=None):
return "a:%s, b:%s, c:%s" % (a, b, c)
我有一个字典,上面有一些(或没有)参数,但也有一个在函数中没有命名参数的键,例如:
d = {'a': 1, 'x': 4, 'b': 2, 'y': 5}
如果我调用以下内容,我将收到错误,因为'x'和'y'不是foo函数中的关键字参数。
foo(**d) # error
是否有一种优雅的方式将参数从字典传递给函数,但只有那些具有与函数参数匹配的键的值。
如果我的参数/参数术语已关闭,请更正我。
答案 0 :(得分:31)
def foo(a = None, b=None, c=None,**extras):
return "a:%s, b:%s, c:%s" % (a, b, c)
这里**extras
将收集所有额外的命名/关键字参数。
答案 1 :(得分:7)
@Ashwini Chaudhary有一种非常pythonic的方法来解决你的问题。但是,它需要更改foo
功能的签名。
如果您不想更改功能签名,可以使用introspection找出您的函数所期望的参数:
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)
答案 2 :(得分:6)
有趣的问题。我认为现实生活中的大多数人都使用@Ashwini Chaudhary方法。
我同意@Rodrigue,有时你无法修改函数(也许是其他人的模块)的调用签名。
当发生这种情况时,使用功能装饰器
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)
来自functools的 @wraps
保持__name__
和__doc__
字符串。你也可以:
FunctionMaker
,但这应该是一种更可重用的方法。