使用dict.fromkeys创建字典后循环修改值时所有键同步变更问题
字典循环修改单键值却全部同步更新的问题与解决
问题现象
使用dict.fromkeys初始化字典后,尝试遍历数据修改指定键对应值的第一个元素时,所有键的数值会同步递增,而非仅目标键。
初始化代码及结果:
times_genus_contaminated = dict.fromkeys(expected_genus,[0,{}]) # 输出:{'Aedes': [0, {}], 'Homo': [0, {}], 'Mus': [0, {}]}
遍历修改的示例代码:
for sample in contaminated_samples: for contamination in sample['contamination']: genus = contamination[0] times_genus_contaminated[genus][0] += 1 print(times_genus_contaminated)
循环处理的示例数据:
['Homo', 'Pan', '9597', 23022, 47.66] ['Homo', 'Gorilla', '9595', 1816, 3.76] ['Mus', 'Mastomys', '35658', 532, 1.11] ['Mus', 'Arvicanthis', '61156', 965, 2.03] ['Aedes', 'Mayaro', '59301', 277, 2.19]
预期输出:
{'Aedes': [1, {}], 'Homo': [2, {}], 'Mus': [2, {}]}
实际输出:
{'Aedes': [5, {}], 'Homo': [5, {}], 'Mus': [5, {}]}
问题根源
dict.fromkeys的实现逻辑是将传入的默认值对象直接复用给所有键。这里的[0, {}]是一个列表对象,字典中所有键对应的都是这个列表的引用。修改任意一个键对应的列表元素,本质是修改这个共享的列表对象,导致所有键的数值同步变化。
解决方案
方案1:修改时拷贝列表
每次修改前,先浅拷贝目标键对应的列表,修改拷贝后的列表再重新赋值给原键,避免操作共享对象:
for sample in contaminated_samples: for contamination in sample['contamination']: print(contamination) genus = contamination[0] temp = times_genus_contaminated[genus][:] # 浅拷贝列表 temp[0] += 1 times_genus_contaminated[genus] = temp
方案2:从根源避免共享对象(更推荐)
使用字典推导式初始化字典,为每个键生成独立的列表对象,后续可直接修改元素:
times_genus_contaminated = {genus: [0, {}] for genus in expected_genus}
此时执行原遍历修改代码即可得到正确结果。
内容的提问来源于stack exchange,提问作者kevin41
相关产品推荐
相关产品推荐

