python3二维字典更新的问题

本文探讨了使用不同方法更新二维字典的行为差异,特别是在使用defaultdict和普通dict时的区别。通过对比两种更新方式,展示了如何避免类型转换导致的问题,并提供了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在使用二维字典的时候,发现了一个有趣的问题, 发现网上对于二维字典的更新方式全是如下方式,其解释也全是因为二维字典的两层key和value之间会混淆

from collections import defaultdict

def addtwodimdict(thedict, key_a, key_b, val):
    adict = thedict.keys()
    if key_a in adict:
        thedict[key_a].update({key_b: val})
    else:
        thedict.update({key_a:{key_b: val}})

那么,使用这种方式,再看一个代码:


from collections import defaultdict


def addtwodimdict(thedict, key_a, key_b, val):
    adict = thedict.keys()
    if key_a in adict:
        thedict[key_a].update({key_b: val})
        
    else:
        thedict.update({key_a:{key_b: val}})
                        
data =[[1000,2,3,2,5,6,7],[1001,4,6,6,3,7,2],[1002,3,6,2,1,6,7],[1003,3,4,6,5,8,0]]

def my_dict(data):
    graph_dict = defaultdict(lambda: defaultdict(lambda: 0))  # 声明一个二维default dict
    for i in range(len(data)):
        val1=data[i][1]
        val2=data[i][2]
        addtwodimdict(graph_dict,val1,val2,data[i][0])
        addtwodimdict(graph_dict,val2,val1,data[i][0])
    return graph_dict


adict= my_dict(data)
print(adict)

输出为:

defaultdict(<function my_dict.<locals>.<lambda> at 0x7fbfa473cbf8>, {2: {3: 1000}, 3: {2: 1000, 6: 1002, 4: 1003}, 4: {6: 1001, 3: 1003}, 6: {4: 1001, 3: 1002}})

可以发现,我们生成的二维字典,声明为defaultdict(lambda: defaultdict(lambda: 0))本来应该是“内层”和“外层”均是default dict的,但是现在只有外层是default dict,因此如果我们执行print(adict[100]), 不会报错keyerror,执行print(adict[100][1000]) 也同样不会报错,因为外层是default dict,所以尽管键100不存在,也不会报错;但是执行print(adict[2][4]) 会报keyerror的错误,因为键[2][4]不存在,且 不是default dict。但是现在为什么在addtwodimdic后,只有外层才是default dict呢?

原因就在于addtwodimdict中,使用了update的更新方式。这种更新方式会使得default dict变回普通的dict, 因此我们如果修改下addtwodimdict函数为:

def addtwodimdict(thedict, key_a, key_b, val):
    thedict[key_a][key_b] =val  #针对default dict,应该这样更新

可以看到,外层和内层均是default dict了,这才是我们想要的结果。这种情况下,无论是print[2][100], 还是print[100],无论键是否存在,均不会报keyerror的错了。至于网上全说二维字典的两层key和value之间会混淆,实际上应该是这全应该是对于普通的dict来说的。

defaultdict(<function my_dict.<locals>.<lambda> at 0x7fbfa473cd90>, {2: defaultdict(<function my_dict.<locals>.<lambda>.<locals>.<lambda> at 0x7fbfa4660d08>, {3: 1000}), 3: defaultdict(<function my_dict.<locals>.<lambda>.<locals>.<lambda> at 0x7fbfa4677c80>, {2: 1000, 6: 1002, 4: 1003}), 4: defaultdict(<function my_dict.<locals>.<lambda>.<locals>.<lambda> at 0x7fbfa4677488>, {6: 1001, 3: 1003}), 6: defaultdict(<function my_dict.<locals>.<lambda>.<locals>.<lambda> at 0x7fbfa4677158>, {4: 1001, 3: 1002})})

如果要使用update来更新二维数组,那么声明的时候就应该声明为普通的字典dict,而且,如果是普通的二维字典dict,只能使用update来更新,使用hedict[key_a][key_b] =val这样的方式会出错。显然,普通的字典,如果输入的键不存在,则返回keyerror,比如:

from collections import defaultdict

def addtwodimdict(thedict, key_a, key_b, val):
    adict = thedict.keys()
    if key_a in adict:
        thedict[key_a].update({key_b: val})
    else:
        thedict.update({key_a:{key_b: val}})
        #thedict[key_a][key_b] =val  #针对default dict
                        
data =[[1000,2,3,2,5,6,7],[1001,4,6,6,3,7,2],[1002,3,6,2,1,6,7],[1003,3,4,6,5,8,0]]

def my_dict(data):
    graph_dict ={}  #尽管是作为二维字典,但是不能写成graph_dict ={{}} 
    for i in range(len(data)):
        val1=data[i][1]
        val2=data[i][2]
        addtwodimdict(graph_dict,val1,val2,data[i][0])
        addtwodimdict(graph_dict,val2,val1,data[i][0])
    return graph_dict

adict= my_dict(data)
print(adict) # 存在
print(adict[100]) #不存在,报错

输出为;

{2: {3: 1000}, 3: {2: 1000, 6: 1002, 4: 1003}, 4: {6: 1001, 3: 1003}, 6: {4: 1001, 3: 1002}}

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-56-f6e50649b40d> in <module>
     31 adict= my_dict(data)
     32 print(adict)
---> 33 print(adict[100])

KeyError: 100


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值