列表理解创建字典的 n 个唯一副本

list comprehension to create n unique copies of a dictionary

我有两个字典键列表:一个 'outer' 字典键列表和一个 'inner' 字典键列表:

outer_keys = ['out1', 'out2', 'out3', 'out4' ]
inner_keys = ['in1', 'in2', 'in3' ]

我正在尝试使用列表理解以编程方式生成类似于以下结构的嵌套字典:

{'out1': {'in1': Decimal('0.00'), 'in2': Decimal('0.00'), 'in3': Decimal('0.00')},
 'out2': {'in1': Decimal('0.00'), 'in2': Decimal('0.00'), 'in3': Decimal('0.00')},
 'out3': {'in1': Decimal('0.00'), 'in2': Decimal('0.00'), 'in3': Decimal('0.00')},
 'out4': {'in1': Decimal('0.00'), 'in2': Decimal('0.00'), 'in3': Decimal('0.00')}
}

我的第一次尝试如下:

from decimal import Decimal
outer_keys = ['out1', 'out2', 'out3', 'out4' ]
inner_keys = ['in1', 'in2', 'in3' ]

z = dict(zip(outer_keys, [dict(zip(inner_keys, [Decimal('0.00') for _ in inner_keys])) for _ in outer_keys]))

从 'outer' 键引用的 'inner' 词典都是唯一的意义上说,这工作正常:

>>> z['out1']['in1'] is z['out2']['in1']
False

但是,对 z 的分配相当难以遵循。所以我试着把它分成两个作业来简化它:

x = dict(zip(inner_keys, [Decimal('0.00') for _ in inner_keys]))
y = dict(zip(outer_keys, [x for _ in outer_keys]))

这不再有效,因为 'outer' 键 'out1'、...、'out4' 的值都引用同一个字典。

>>> y['out1']['in1'] is y['out2']['in1']
True

所以分配给一个内部字典中的一个项目会改变它们中的相应值:

>>> y['out1']['in1']
Decimal('0.00')
>>> y['out2']['in1']
Decimal('0.00')
>>> y['out1']['in1']=Decimal('1.00')
>>> y['out2']['in1']
Decimal('1.00')
>>> 

我已经尝试使用我能想到的所有东西来代替 x 在分配给 y 的列表理解中(包括,例如,copy.deepcopy(x) 和一个列表- slice like [x][:][0],但无论我做什么,我都无法让 python 为每个外部键值创建 x 引用的字典的唯一副本。当然,除非回到原来的冗长和对 z.

不可读的赋值

我也很难理解为什么 [Decimal('0.00') for _ in inner_keys] 生成三个唯一的 Decimal 对象,但 [x for _ in outer_keys] 生成四个对单个字典的引用。以及如何编写一个列表理解,它将生成 n 个字典的唯一副本 x.

编辑 1:我似乎没有足够仔细地检查我尝试过的一些东西是否真的有效。正如@MichaelButscher 在下面的评论中正确指出的那样,在 y 的赋值中使用 x.copy() 而不是 x 将解决我的问题,尽管 copy.deepcopy(x) 似乎也是如此我没有意识到它在起作用。

所以这当然是我可以解决这个问题的一种方法。

我也喜欢@Ahmed I. Elsayed 在下面发布的字典理解解决方案。

这两个都比我最初对 z

的复杂分配要清晰得多

Python 提供 dict 理解(也设置 comps!)

# IDLE ( I reformatted )

my_dict = { key: inner_keys for key in outer_keys }
my_dict

{
 'out1': ['in1', 'in2', 'in3'],
 'out2': ['in1', 'in2', 'in3'],
 'out3': ['in1', 'in2', 'in3'],
 'out4': ['in1', 'in2', 'in3']
}

如果你想像你使用的那样将某些东西应用到第二个列表 Decimal,多种方式

my_dict = { key: [i.upper() for i in inner_keys ] for key in outer_keys }
my_dict

{
 'out1': ['IN1', 'IN2', 'IN3'],
 'out2': ['IN1', 'IN2', 'IN3'],
 'out3': ['IN1', 'IN2', 'IN3'],
 'out4': ['IN1', 'IN2', 'IN3']
}

my_dict = { key: map(str.upper, inner_keys) for key in outer_keys }
# same output as above, trimmed for readability

根据需要自定义,或在此处的评论中提问。

我想归功于我学习 dictcomps 的地方,我第一次看到它们是在天才 Luciano Ramalho 的精彩著作 Fluent Python 中。