通过理解更新列表中的字典项

扬·萨卡洛斯(Jan Sakalos)

我有一本字典,希望将其用作模板以使用更新的字典项生成多个字典。在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对我来说适得其反。

打nor

特别是我不确定...

在理解中更新Python字典的事情有点复杂,因为它们是可变的。python为什么dict.update()不返回对象?最佳答案建议您当前的解决方案。我个人可能会在此处使用常规的for循环,以确保代码清晰易读。

这是准备测试数据的正确方法吗?

  1. 通常在单元测试中,您将同时测试边缘情况和常规情况(不过,您不想重复自己)。通常,您需要拆分测试,以便每个测试都有其自己的名称,以解释为什么存在该测试,以及可能还有一些其他数据,这些数据可以帮助某些局外人了解确保这种情况正确运行的重要性。将所有场景放到一个列表中,然后针对每个场景进行测试,而又不给读者其他上下文(至少以测试用例名称的形式),使读者更难区分这些案例并判断它们是否全部真的需要。
  2. 将每个方案放在单独的测试用例中有时可能会有些乏味,但是如果任何测试失败,则可以立即判断出软件的哪一部分失败了。如果您觉得自己编写了太多的单元测试,那么也许其中一些涵盖了相同的场景。
  3. 在进行单元测试时,性能很少是最优先考虑的事情。通常,更重要的是使测试次数最少,但足以确保软件正确运行。另一个优先事项是使测试易于理解。参见下面的另一种说法(不一定是性能更高,但希望更清晰易懂)。

替代解决方案

您可以使用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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章