最近在使用二维字典的时候,发现了一个有趣的问题, 发现网上对于二维字典的更新方式全是如下方式,其解释也全是因为二维字典的两层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