现在开始学习字典,字典也是写程序过程中非常重要的东西,但是字典不属于序列,**属于映射(mapping)**这种数据结构。
字典(dict)
它和列表都是存储对象的容器。列表有一个问题,就是元素贼多的时候,如果不知道索引对应的内容,查询起来很费劲,就像番外练习中移除英雄的设计部分那样,要么很麻烦得输入英雄信息,要么用索引搜,多了就得挨个找。字典就不一样,字典之所以叫字典,就是因为查询“元素”很方便,就像不同字典搜拼音开头字母再找音节之类的,程序中的字典的“元素”都有自己唯一的名字,以便于迅速查找,这个唯一名字称为键(key)。“元素”的值同样叫value,所以字典也叫键值对(key-value)结构,不过字典里面这些不叫元素(所以我加了双引号),每个键值对叫一个项(item)。字典用{}表示,由于键值对结构,所以写每个项的时候要写为key:value的形式,各项之间逗号隔开。
dict1 = {'铁血剑豪': 49, '源计划:林': 99, '冰雪节限定': '买不了'}
print(dict1, type(dict1))
{'铁血剑豪': 49, '源计划:林': 99, '冰雪节限定': '买不了'} <class 'dict'>
其中,键可以是任意不可变对象,而值可以是任意对象。注意,前面说到键是唯一的名字,所以每个项的键不能一样,一样的时候后面的会替换前面的,前面的值也会被后面的替代。
dict1 = {'铁血剑豪': 49, '源计划:林': 99, '铁血剑豪': '买不了'}
print(dict1, type(dict1))
{'铁血剑豪': '买不了', '源计划:林': 99} <class 'dict'>
注意大括号中括号小括号等可以跨行写。字典通过键获取值,相当于列表用索引获取元素。
dict1 = {
'铁血剑豪': 49,
'源计划:林': 99,
'冰雪节限定': '买不了'
}
print(dict1['源计划:林'])
99
键不存在的时候就会报错。
字典的操作
除了上述的用{}创建字典之外,用dict()函数也可以创建字典。参数名就是键,参数值就是值,不过这样建立的字典,所有的键都是字符串。
dict2 = dict(q='阿尔法突袭', w='冥想', e='忘了', r='高原血统')
print(dict2)
{'q': '阿尔法突袭', 'w': '冥想', 'e': '忘了', 'r': '高原血统'}
序列中只有两个值的序列叫双值序列(如(1,2),[1,2],'12’等);如果一个序列中某元素也是一个序列,这个元素就叫子序列。如果一个序列中的元素,都是双值子序列,那么这个序列可以直接转换为字典,同样用的是dict()函数,这个方法的键就不用一定是字符串了。
dict3 = dict([('武器大师', '贾克斯'), ('武神', 99)])
print(dict3)
{'武器大师': '贾克斯', '武神': 99}
len()函数用来获取字典里面键值对个数。
print(len(dict3))
2
in,not in看字典里面是否包含或是否不包含指定的键。
print('武器大师' in dict3)
print('贾克斯' not in dict3)
'贾克斯’是值,不是键,因此:
True
True
用键获取值,上面也讲到了,但是要注意如上面演示的print(dict1[‘源计划:林’]),键是字符串,那[]里面一定要加’',是数字则不用,总而言之就是输入的键要和字典里面的键完全一致。
dict3 = dict([('武器大师', '贾克斯'), (1, 99)])
print(dict3[1])
99
例如print(dict3[‘1’]),则会报错。但是如果把键赋值给某个变量,那么就不用管’'的事情了。
dict3 = dict([('武器大师', '贾克斯'), ('武神', 99)])
s = '武神'
print(dict3[s])
99
根据键获取值的方法还有.get(key[,default]),注意中括号里面的东西可选参数,自己使用的时候不一定需要输入这个,这个方法的好处在于没有你输入的键时不会报错,会输出None。
dict3 = dict([('武器大师', '贾克斯'), ('武神', 99)])
print(dict3.get('武神'))
print(dict3.get(1))
99
None
可选参数是一个默认值,如果输入一个默认值,那么在没有找到你输入的键的时候,就返回默认值,而不是None。
print(dict3.get(1,'我不到啊'))
我不到啊
修改字典
dict1[key]=value即可,注意修改的是值。
dict3['武神'] = 129
print(dict3)
{'武器大师': '贾克斯', '武神': 129}
如果中括号里面输入的键不存在,就会添加输入的新键值对。
dict3['复仇武神'] = 49
print(dict3)
{'武器大师': '贾克斯', '武神': 99, '复仇武神': 49}
.setdefault(key[,default])方法也是用来添加项的,输入的key已经存在字典中的话就返回key的值,不会有任何修改,也就是说就算输入了新的值,值也不变,除非key是新的。
dict3.setdefault('武神', 129)
print(dict3) # 结果不会变成武神对应129
dict3.setdefault('SKT 贾克斯', 79)
print(dict3)
{'武器大师': '贾克斯', '武神': 99, '复仇武神': 49}
{'武器大师': '贾克斯', '武神': 99, '复仇武神': 49, 'SKT 贾克斯': 79}
所选字典.update([other])用于将其他字典的项加到所选字典里面。
dict3.update(dict1)
print(dict3)
{'武器大师': '贾克斯', '武神': 99, '复仇武神': 49, 'SKT 贾克斯': 79, '铁血剑豪': 49, '源计划:林': 99, '冰雪节限定': '买不了'}
注意,如果两个字典有相同键,那么其他字典的key将会替代所选字典的key。
.copy()用于对字典浅复制,也就是只复制值,这种操作返回的新字典会创造出一个新对象,而不像赋值操作那样id相同。
dict4 = dict3
dict5 = dict3.copy()
print(id(dict3))
print(id(dict4))
print(id(dict5))
2207672546552
2207672546552
2207670353496
因此,复制的字典被修改不会影响原字典。由于值可以是任意对象,所以值本身也可以是字典,在这种情况下,也就是值属于可变对象的时候,浅复制将不会复制这一部分,这就是浅复制“浅”的地方。
dict6 = {
'铁血剑豪': {'源计划:林': 99},
'冰雪节限定': '买不了'
}
dict7 = dict6.copy()
print(dict6, dict7)
dict7['铁血剑豪']['源计划:林'] = 199
print(dict6, dict7)
{'铁血剑豪': {'源计划:林': 99}, '冰雪节限定': '买不了'} {'铁血剑豪': {'源计划:林': 99}, '冰雪节限定': '买不了'}
{'铁血剑豪': {'源计划:林': 199}, '冰雪节限定': '买不了'} {'铁血剑豪': {'源计划:林': 199}, '冰雪节限定': '买不了'}
可以看出,修改字典里面的字典使独立的两个字典dict6和dict7并没有展现出独立的效果,这就是浅复制不能复制可变对象的原因。
字典项的删除
del除了删元素,变量之外,同样可以删除项。
del dict3['冰雪节限定']
print(dict3)
{'武器大师': '贾克斯', '武神': 99, '复仇武神': 49, 'SKT 贾克斯': 79, '铁血剑豪': 49, '源计划:林': 99}
.popitem()随机删除一个项,但是其实一般默认删最后一个。有返回值,返回被删的项,是以元组结构显示,分别是key和value,当然需要打印才能知道。注意这个方法删不了空字典,会报错。
r = dict3.popitem()
print(r)
print(dict3)
('源计划:林', 99)
{'武器大师': '贾克斯', '武神': 99, '复仇武神': 49, 'SKT 贾克斯': 79, '铁血剑豪': 49}
.pop(key[,default])根据key删项,但是只返回值。key不存在就返回报错,除非也写一个备选参数。
t = dict3.pop('铁血剑豪')
print(t)
print(dict3)
49
{'武器大师': '贾克斯', '武神': 99, '复仇武神': 49, 'SKT 贾克斯': 79}
q = dict3.pop('天人合一', '没有啊')
print(q)
print(dict3)
不打印q也没事,反正不会报错了。
没有啊
{'武器大师': '贾克斯', '武神': 99, '复仇武神': 49, 'SKT 贾克斯': 79}
.clear()删除所有项,也就是清空字典。
dict3.clear()
print(dict3)
{}