You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何对从pickle文件读取的同结构字典逐键求和?

解决嵌套字典逐键求和时的数值异常问题

我一眼就看出问题所在啦——你的代码里用update方法直接复制字典时,做的是浅拷贝,也就是说accumulated_damage里的内层字典其实是和old_damage、current_damage里的内层字典共享同一个内存引用的。尤其是当你测试用同一个字典自身求和时,第一次修改accumulated_damage[i][j]的时候,其实也偷偷修改了current_damage里对应的值,等到循环到下一个外层键时,你加的就不是原始的1.00E+00,而是已经被修改过的2.00E+00,自然就得出了3.00E+00的错误结果。

那怎么解决呢?我们需要创建一个完全独立的新字典,而不是直接引用原字典的内层对象。这里给你两种靠谱的写法:

方法一:逐层级创建新字典

这种方法最直观,手动遍历每一层键,创建新的内层字典来存储求和结果:

import pickle

# 先读取两个字典(假设你已经完成unpickle步骤)
with open('old_damage.pkl', 'rb') as f:
    old_damage = pickle.load(f)
with open('current_damage.pkl', 'rb') as f:
    current_damage = pickle.load(f)

accumulated_damage = {}
# 遍历外层键
for outer_key in old_damage.keys():
    # 为每个外层键创建一个新的内层字典
    accumulated_damage[outer_key] = {}
    # 遍历内层键
    for inner_key in old_damage[outer_key].keys():
        # 确保两个字典都有该键(你的try-except可以保留,防止结构不一致)
        try:
            old_val = float(old_damage[outer_key][inner_key])
            current_val = float(current_damage[outer_key][inner_key])
            # 求和后转成你需要的科学计数法格式
            summed_val = f"{old_val + current_val:.2E}"
            accumulated_damage[outer_key][inner_key] = summed_val
        except KeyError:
            # 如果某一方没有这个键,可以选择保留原有的值或者跳过
            if outer_key in current_damage and inner_key in current_damage[outer_key]:
                accumulated_damage[outer_key][inner_key] = current_damage[outer_key][inner_key]
            else:
                accumulated_damage[outer_key][inner_key] = old_damage[outer_key][inner_key]

方法二:用字典推导式简化代码

如果你的两个字典结构完全一致(题目里说结构相同),可以用嵌套的字典推导式来更简洁地实现:

accumulated_damage = {
    outer_key: {
        inner_key: f"{float(old_damage[outer_key][inner_key]) + float(current_damage[outer_key][inner_key]):.2E}"
        for inner_key in old_damage[outer_key]
    }
    for outer_key in old_damage
}

这种写法前提是两个字典的外层键和内层键完全对应,不需要处理KeyError。如果有结构不一致的可能,还是加上try-except更稳妥。

为什么你的原代码会出问题?

再回头看你的代码:

accumulated_damage = {}
accumulated_damage.update(old_damage)  # 这里accumulated_damage的内层字典是old_damage的引用
accumulated_damage.update(current_damage)  # 相同外层键的内层字典被替换成current_damage的引用
for i in old_damage.keys():
    for j in old_damage[i].keys():
        try:
            addition = float(current_damage[i][j])+float(old_damage[i][j])
            accumulated_damage[i][j]=addition  # 这里修改的是current_damage的内层字典(如果update后引用的是它)
        except KeyError:
            continue

当你用自身求和时,old_damage和current_damage是同一个对象,第一次循环修改accumulated_damage['1000']['13']时,其实也修改了current_damage['1000']['13']的值为2.0。等到循环到['1001']时,float(current_damage[i][j])已经是2.0了,加1.0就得到3.0。

所以核心就是要避免共享内层字典的引用,必须创建新的字典对象来存储结果。

内容的提问来源于stack exchange,提问作者nat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:49:05