python创建dict的方法及坑

说到在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': []} # dict1
{'a': ['mm'], 'b': ['mm'], 'c': ['mm']} # dict2

看到了吧,如果直接用等于号赋值,那么只会对对应位置的值进行修改,而用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。

暂时先写到这儿 该睡了嘎嘎

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值