在方法调用args中,如何覆盖unpacked dict的关键字参数?

时间:2017-06-27 15:43:43

标签: python dictionary keyword-argument

我试图在函数调用中使用模板关键字args(通过dict和关键字参数),同时能够覆盖一些参数。

例如,如果我们从包含行template_kvps = {'a': 1, 'b': 2}

的模块mymod开始

我可以:

import mymod

def func(**kwargs):
    pass

func(**mymod.template_kvps)

然后我可以在template_kvps内访问我的func()。但我希望能够以最小的开销为a传递不同的值。

所有我能想到的是在函数调用之前更改字典:kvps = {**template_kvps, 'a': 3}; func(**kvps),但这是行数的两倍,我在每个周围使用此函数几次1000个测试脚本。

理想情况下,我希望重新定义func以便我可以像func(**mymod.template_kvps, a=3)那样做,但事实上,Python错误与重复参数有关。

btw我很高兴考虑更改template_kvps的格式。

注意稍后添加我的问题有一些很好的答案(而且我已经接受了我认为对我所问的最佳答案),但我认为我'我问了一件坏事。我建议这是一个设计问题,如果我想要这样的默认参数,我认为最好用默认参数而不是模板字典创建一个包装器方法,如下所示:

def func_template(a=1, b=2):
    func(a, b)

func_template(a=3)

6 个答案:

答案 0 :(得分:6)

您可以使用内置dict类型来实现此目的。它接受另一个dict作为参数,并接受其他键值对作为关键字参数(优先于其他dict中的值)。

因此,您可以通过dict(template_vars, a=1)创建更新的字典。

您可以将此dict展开为关键字参数:func(**dict(...))

就像那样,无需更改功能的签名,您可以根据需要更新/添加任意数量的键值对。

答案 1 :(得分:1)

你可以这样做一行:

func(**{**mymod.template_kvps, 'a': 3})

但乍一看这可能并不明显,但与你之前所做的一样明显。

我建议使用多个模板(例如template_kvps_without_a),但这取决于您的具体用例:

func(**mymod.template_kvps_without_a, a=3)

答案 2 :(得分:1)

我会考虑函数装饰器,因为它保持语法与您请求的大致相同。实现看起来像:

def combine(func):
  def wrapper(*args, **kwargs):
    fargs = {}
    if args and isinstance( args[0], dict ):
      fargs = args[0].copy()
    fargs.update(kwargs)
    return func(**fargs)
  return wrapper


@combine
def funky(**kwargs):
  for k,v in kwargs.iteritems():
    print "%s: %s" % (k, v)

# All of these work as expected
funky( {'a': 1, 'b': 2}, a=3 )
funky( {'a': 1, 'b': 2} )
funky( a=3 )

答案 3 :(得分:0)

您可以使用更新要更改的任何值的函数。 (编辑以便不修改原始字典。)

import mymod

def replace(dict1, dict2):
  ans = dict1.copy()
  ans.update(dict2)
  return ans

def func(**kwargs):
  pass

func(replace(mymod.template_kvps, {'a':3}))

答案 4 :(得分:0)

这应该有效

func(a=3, **{key: value for key, value in mymod.template_kvps.items() if key != 'a')})

但是我建议写另一行代码,而不是混淆它。

答案 5 :(得分:0)

我将模板参数更改为位置参数,并将键覆盖为**kwargs

def func(template_dict, **kwargs):
    updated_dict = {**template_dict, **kwargs}
    return updated_dict

print(func({'a':1, 'b':2}, a=3)) # {'a': 3, 'b': 2}

请注意,双解包语法需要Python 3.5+。在旧版本中,请使用:

updated_dict = template_dict.copy()
updated_dict.update(kwargs)