我有两个字典键列表:“外部”字典键列表和“内部”字典键列表:
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]))
从“外部”键引用的“内部”字典都是唯一的意义上说,这可以正常工作:
>>> 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]))
This no longer works because the values of the 'outer' keys 'out1', ..., 'out4' all reference the same dictionary.
>>> y['out1']['in1'] is y['out2']['in1']
True
So assigning to an item in one inner dictionary changes the corresponding value in them all:
>>> y['out1']['in1']
Decimal('0.00')
>>> y['out2']['in1']
Decimal('0.00')
>>> y['out1']['in1']=Decimal('1.00')
>>> y['out2']['in1']
Decimal('1.00')
>>>
I've tried using everything I can think of in place of x in the list comprehension in the assignment to y (including, e.g., copy.deepcopy(x) and a list-slice like [x][:][0], but no matter what I do, I cannot get python to create a unique copy of the dictionary referenced by x for each outer key value. Except of course by going back to the original lengthy and unreadable assignment to z.
I'm also having trouble understanding why [Decimal('0.00') for _ in inner_keys] generates three unique Decimal objects, but [x for _ in outer_keys] generates four references to a single dict. And how to write a list comprehension which will generate n unique copies of the dict x.
Edit 1: It seems I wasn't careful enough in checking whether some of things I tried were actually working. As @MichaelButscher correctly points out in his comment below, using x.copy() rather than x in the assignment to y will resolve my issue, as so it seems did copy.deepcopy(x) even though I didn't realize it was working.
So that is certainly one way I could fix this.
I also like the dict comprehension solution that @Ahmed I. Elsayed posted below.
Both of these are much cleaner than my original complicated assignment to z