提问人:joel 提问时间:6/27/2017 最后编辑:joel 更新时间:7/10/2020 访问量:6710
在方法调用参数中,如何覆盖解压缩字典的关键字参数?
In method call args, how to override keyword argument of unpacked dict?
问:
为了方便起见,我尝试在函数调用中使用模板关键字参数(通过 dict 和关键字参数),同时能够覆盖一些参数。
例如,如果我们从一个包含以下行的模块 mymod 开始template_kvps = {'a': 1, 'b': 2}
我只能:
import mymod
def func(**kwargs):
pass
func(**mymod.template_kvps)
然后我就可以访问我的内部.但我希望能够以最小的开销传递不同的值。template_kvps
func()
a
我能想到的就是在函数调用之前更改字典:,但这是行数的两倍,我在大约 1000 个测试脚本中的每一个都多次使用这个函数。kvps = {**template_kvps, 'a': 3}; func(**kvps)
理想情况下,我想重新定义,以便我可以像 sth 一样做 sth,但事实上,Python 错误与重复参数有关。func
func(**mymod.template_kvps, a=3)
顺便说一句,我很高兴考虑更改 .template_kvps
编辑(将在某个时候移动到答案)我可以改用包装方法
def func_template(a=1, b=2):
func(a, b)
func_template(a=3)
答:
你可以有一个函数来更新你想要更改的任何值。(已编辑,因此不会修改原始词典。
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}))
评论
这应该有效
func(a=3, **{key: value for key, value in mymod.template_kvps.items() if key != 'a')})
但是,我建议再写一行代码,不要混淆它。
你可以像这样在一行中做到这一点:
func(**{**mymod.template_kvps, 'a': 3})
但这乍一看可能并不明显,但与您之前所做的一样明显。
我的建议是拥有多个模板(例如),但这取决于您的具体用例:template_kvps_without_a
func(**mymod.template_kvps_without_a, a=3)
为此,可以使用内置类型。它接受另一个字典作为参数,并接受其他键值对作为关键字参数(优先于另一个字典中的值)。dict
因此,您可以通过 创建更新的字典。dict(template_vars, a=1)
您可以将此字典展开为关键字参数:.func(**dict(...))
这样,就不需要更改函数的签名,您可以根据需要更新/添加任意数量的键值对。
我会考虑函数装饰器,因为这会使语法与您要求的语法基本相同。实现如下所示:
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 )
我会将模板参数更改为位置参数,并将键覆盖为 .**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)
评论
func(mymod.template_kvps)
func(**mymod.template_kvps)