说到在python中创建dict,我们很自然的就想到用mydict = {},然后对其赋值。
mydict = {}
mydict['a'] = 123
mydict['b'] = 'ping'
mydict['c'] = [1,2,3]
mydict
Out[12]: {'a': 123, 'b': 'ping', 'c': [1, 2, 3]}
但是当我们想免于一个一个手动添加的时候,坑就来了
1. dict.fromkeys
对于已知key来创建dict,dict.fromkeys其实是个好东西。 但是看下面两个例子:
dict1 = dict.fromkeys(('a','b','c'),[])
dict1['a'] = ['mm']
print(dict1)
dict2 = dict.fromkeys(('a','b','c'),[])
dict2['a'].append('mm')
print(dict2)
{'a': ['mm'], 'b': [], 'c': []}
{'a': ['mm'], 'b': ['mm'], 'c': ['mm']}
看到了吧,如果直接用等于号赋值,那么只会对对应位置的值进行修改,而用append对内容进行添加时却会对所有的value都进行修改。 这个问题的原因显而易见,当我们用dict.fromkeys创建dict时,传入的第二个参数 [ ] 被所有keys使用,即每个key指向的value是同一个地址。并不是将[ ] 复制了3份,而是一份[ ] 被所有key指向使用。
所以如果我们用等于号赋值的方法,相当于把 a 的这个指针指向了一块儿新的区域,而对bc没有影响。可是如果对a进行append,那么其实修改的是abc共同拥有的那块儿value,所以bc的值也会跟着变。
那么我们又想用这种方法,又想不让bc的值跟着a变该怎么办呢? 首先确定的是,得用等于号。其次,不能改变原有的那块儿公共value区域,所以:
dict3=dict.fromkeys(('a','b','c'),[])
dict3['a'] = dict3['a']+['55']
print(dict3)
{'a': ['55'], 'b': [], 'c': []}
哎嗨,这就成了。 但还会想我如果用copy.deepcopy一类的呢?我把新的value赋值给了a啊,那我们瞅瞅:
dict4=dict.fromkeys(('a','b','c'),[])
dict4['a']=copy.deepcopy(dict4['a'].append('66'))
print(dict4)
{'a': None, 'b': ['66'], 'c': ['66']}
看到了吧,是把a先append以后再copy的啊,所以公共区域value是已经被改变了。
2.字典键值元组表
还有一种通过key-value的元组表来创建dict
dict5=dict([('name','Allen'),('age',21),('gender','male')])
print(dict5)
{'gender': 'male', 'age': 21, 'name': 'Allen'}
这个没问题哈,妥妥儿的。 但是我们要看的情况是,如果value是个list,并且我想动态生成怎么办。 举个例子:我想根据id中的前四位字母把他们分到对应的key下
ids = ['1233000004567', '1256000004532', '1233000001101', '1256000000099']
按照我们的想法,结果应该是
{'1233':['1233000004567','1233000001101'], '1256':['1256000004532', '1256000000099']}
但如果我用元组表来创建:
lis = []
for id in ids:
lis.append((id[:4],id))
dict6 = dict(lis)
print(lis)
print(dict6)
lis
Out[47]:
[('1233', '1233000004567'),
('1256', '1256000004532'),
('1233', '1233000001101'),
('1256', '1256000000099')]
dict6
Out[48]: {'1233': '1233000001101', '1256': '1256000000099'}
瞧瞧,又被覆盖了。所以对于要动态增加的情况,不能用元组表来生成dict。
暂时先写到这儿 该睡了嘎嘎
|