我有一本字典,希望将其用作模板以使用更新的字典项生成多个字典。在pytest的单元测试中,此列表应用作测试目的的数据集。
我在代码中使用以下构造(不包括检查):
def _f(template,**kwargs):
result = [template]
for key, value in kwargs.items():
result = [dict(template_item,**dict([(key,v)])) for v in value for template_item in result]
return result
template = {'a': '', 'b': '', 'x': 'asdf'}
r = _f(template, a=[1,2],b=[11,22])
pprint(r)
[{'a': 1, 'b': 11, 'x': 'asdf'},
{'a': 2, 'b': 11, 'x': 'asdf'},
{'a': 1, 'b': 22, 'x': 'asdf'},
{'a': 2, 'b': 22, 'x': 'asdf'}]
我想问一下该结构是否足以构建良好的结构-可能可以更有效地编写它。
这是准备测试数据的正确方法吗?
编辑:特别是我不确定
[dict(template_item,**dict([(key,v)])) for v in value for template_item in result]
和
dict(template_item,**dict([(key,v)]))
在我考虑dict.update()但不适合理解之前,因为它不返回字典。
然后我在想像这样的简单语法
d = {'aa': 11, 'bb': 22}
dict(d,x=33,y=44)
{'aa': 11, 'bb': 22, 'x': 33, 'y': 44}
但是我无法通过变量传递键值。而创建仅解压缩它的dict对我来说适得其反。
特别是我不确定...
在理解中更新Python字典的事情有点复杂,因为它们是可变的。在python为什么dict.update()不返回对象?最佳答案建议您当前的解决方案。我个人可能会在此处使用常规的for循环,以确保代码清晰易读。
这是准备测试数据的正确方法吗?
您可以使用itertools.product
以简化您的代码。template
可以删除该参数(因为您可以在中传递模板变量名称及其可能的值**kwargs
):
from pprint import pprint
import itertools
def _f(**kwargs):
keys, values = zip(*(kwargs.items())) # 1.
subsets = [subset for subset in itertools.product(*values)] # 2.
return [
{key: value for key, value in zip(keys, subset)} for subset in subsets
] # 3.
r = _f(a=[1, 2], b=[11, 22], x=['asdf'])
pprint(r)
现在,这些步骤中的每一个都发生了什么:
步骤1.将关键字dict拆分为键和值。这很重要,因此您将每次都固定遍历这些参数的顺序。此时的键和值如下所示:
keys = ('a', 'b', 'x')
values = ([1, 2], [11, 22], ['asdf'])
第2步。计算值的笛卡尔积,这意味着您从每个values
列表中获取取值的所有可能组合。该操作的结果如下:
subsets = [(1, 11, 'asdf'), (1, 22, 'asdf'), (2, 11, 'asdf'), (2, 22, 'asdf')]
步骤3.现在,您需要将每个键映射到每个子集中的相应值,因此,列表和dict的理解应该是您使用先前方法计算出的结果:
[{'a': 1, 'b': 11, 'x': 'asdf'},
{'a': 1, 'b': 22, 'x': 'asdf'},
{'a': 2, 'b': 11, 'x': 'asdf'},
{'a': 2, 'b': 22, 'x': 'asdf'}]
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句