PYTHON 学习第五章 之 字典
字典的介绍
本章介绍一种可通过名称来访问其各个值的数据机构。这种数据结构称为映射(mappeing)。字典是python中唯一的内置映射类型,其中的值不按顺序排序,而是存储在键下。键可以是数,字符串或元组(听到映射和键值对,我就联想到了map, 也是无序的,也是也是映射,也是键值对)。果然语言与语言之间都是相同的,万变不离其宗。
创建字典
语法:dict ={k:v}
phoneBook ={'张三':'135123456','李四':'7895412123','王五':'422335455'}
字典由键及其相应的值组成,这种键-值对称为项(Item)。在前面的示例中,键为名称,而值为电话号码。每个键和值中间以冒号(:)分割,项之间用逗号分割,而整个字典放在花括号内。同样也可以创建空字典 如:{}
函数 dict
与list,tuple和str一样,dict其实根本就不是函数,而是一个类。
可使用函数 dict 从其他映射(如其他字典)或键-值对序列创建字典。其中包含指定映射中的所有项。如果调用这个函数没有提供任何实参,将返回一个空字典。
d = dict(); print(d) #运行结果 {}
如果映射也是字典(毕竟字典是Python中唯一的内置映射类型),可不是用函数dict,而是使用字典方法copy,后续将介绍到。
注意:必须为一对(两个)才有效,否则报错
list :
item =[['name','张三'],['age',18]] d = dict(item); print(d) print(d['name']) #运行结果 {'name': '张三', 'age': 18} 张三
错误示范
案例一:列表中给三个?好像拨错了( •̀ ω •́ )y
item =[['name','张三','xxx'],['age',18,'xxx']] d = dict(item); print(d) print(d['name']) #运行结果 Traceback (most recent call last): File "D:/develTools/PycharmProjects/project1/venv/Include/test3.py", line 3, in <module> d = dict(item); ValueError: dictionary update sequence element #0 has length 3; 2 is required
案例二:单数不行?2的倍数可以把?糟糕 也报错了 5555
item =[['name','张三','xxx','aaa'],['age',18,'xxx','aaa']] d = dict(item); print(d) print(d['name']) #运行结果 Traceback (most recent call last): File "D:/develTools/PycharmProjects/project1/venv/Include/test3.py", line 3, in <module> d = dict(item); ValueError: dictionary update sequence element #0 has length 4; 2 is required
案例五: 这样同样也是不行的,
item =[['name','张三','xxx','aaa']] d = dict(item); print(d) print(d['name']) #运行结果 Traceback (most recent call last): File "D:/develTools/PycharmProjects/project1/venv/Include/test3.py", line 3, in <module> d = dict(item); ValueError: dictionary update sequence element #0 has length 4; 2 is required
案例六:这样是没有问题的。
item =[['name','张三']] d = dict(item); print(d) print(d['name']) #运行结果 {'name': '张三'} 张三
描述能力不行,雷我都趟完了,测试总结:只有单个列表中为是两个才可以,
tuple: 就不演示错误示范了,结果肯定和上面一样
item =(('name','张三'),('age',18)) d = dict(item); print(d) print(d['name']) #运行结果 {'name': '张三', 'age': 18} 张三
这样也是可以的
item =[('name','张三'),('age',18)] d = dict(item); print(d) print(d['name']) #运行结果 {'name': '张三', 'age': 18} 张三
基本的字典操作
字典的基本行为在很多方面都类似于序列
- len(d):返回字典d包含的项 (键-值对)数。
- d[k]返回与键k相关联的值。
- d[k]=v 将值v关联到键k
- del d[k] 删除键为k的项
- k in d 检查字典d 是否包含键为k的项
虽然字典和列表有多个相同之处,但也有一些重要的不同之处。
- 键的类型:字典中的键可以为整数,但非必须为整数。字典中的键可以是任何不可变的类型,如浮点数(实数)、字符串或数组。
- 自然添加:即便是字典中原本没有键,也可以给它赋值,这将在字典中创建一个新项。然而,如果不使用append或其他类似的方法,就不能给列表中没有元素赋值。
d = dict(); print(d) d['name']='张三' print(d) #运行结果’ {} {'name': '张三'}
- 成员资格:表示k in d(其中d是一个字典)查找的是键而不是值,而表达式v in l(其中l是一个列表)查找的是值而不是索引。这看似太不一致,习惯之后就好了。毕竟如果字典包含指定的键,检查相应的值就很容易。
d = dict(); d['name']='张三' d['sex']='男' print('name' in d) #运行结果 True
相比检查列表是否包含指定的值,检查字典是否包含指定的键的效率更高。数据结构越大,效率差距就越大。
将字符串设置格式功能用于字典
可使用字符串格式设置功能来设置值的格式,这些值是作为命名或非命名参数提过给format的。在有些情况,通过在字典中存储一系列命名的值,可让格式设置更容易些。例如,可在字典中包含各种信息,这样只需要在格式字符串中提取所需的信息即可。为此必须使用format_map来指出你将通过一个映射来提供所需的信息。
案例:
person={'name':'张三','sex':'男','age':18}
info='姓名:{name},性别:{sex},年龄:{age}'.format_map(person)
print(info)
#运行结果
姓名:张三,性别:男,年龄:18
form 和 form_map 有什么区别?请看format 输出案例
person={'name':'张三','sex':'男','age':18}
info='姓名:{pe[name]},性别:{pe[sex]},年龄:{pe[age]}'.format(pe=person)
print(info)
#运行结果
姓名:张三,性别:男,年龄:18
字典方法:
clear:删除所有的字典项,这种操作属于就地执行(就像list.sort),因此返回为None
person={'name':'张三','sex':'男','age':18}
person.clear()
print(person)
#运行结果
{}
copy:返回一个新字典,其包含的键-值对与原来的字典相同(这个方法执行的是浅复制,因为值本身是原件,而非副本)。
案例:
person1={'name':'张三','sex':'男','age':18,'hobby':['篮球','rap','音乐']}
#复制一份给 person2
person2=person1.copy()
#这里是替换而不是修改
person1['name']='李四'
person2['name']='王五'
print(person1)
print(person2)
#运行结果
{'name': '李四', 'sex': '男', 'age': 18, 'hobby': ['篮球', 'rap', '音乐']}
{'name': '王五', 'sex': '男', 'age': 18, 'hobby': ['篮球', 'rap', '音乐']}
上面的案例只是将 每个用户的name 进行替换了,好像结果没啥问题?那为什么说是原件呢?原来当替换副本中的值时,原件不受影响。然而,如果修改副本中的值(就地修改不是替换),原件就会受到影响。
案例:
person1={'name':'张三','sex':'男','age':18,'hobby':['篮球','rap','音乐']}
#复制一份给 person2
person2=person1.copy()
#这里是替换而不是修改
person1['hobby'].remove('篮球')
person2['name']='王五'
print(person1)
print(person2)
#运行结果
{'name': '张三', 'sex': '男', 'age': 18, 'hobby': ['rap', '音乐']}
{'name': '王五', 'sex': '男', 'age': 18, 'hobby': ['rap', '音乐']}
???person2的 hobby 也居然被删除了,为了解决这种问题,那么就需要深复制,使用copy中的 deepcopy 函数
需要引入 from copy import deepcopy
from copy import deepcopy person1={'name':'张三','sex':'男','age':18,'hobby':['篮球','rap','音乐']} #复制一份给 person2 person2=deepcopy(person1) #这里是替换而不是修改 person1['hobby'].remove('篮球') person2['name']='王五' print(person1) print(person2) #运行结果 {'name': '张三', 'sex': '男', 'age': 18, 'hobby': ['rap', '音乐']} {'name': '王五', 'sex': '男', 'age': 18, 'hobby': ['篮球', 'rap', '音乐']}
fromkeys:创建一个新字典,其中包含指定的键,且每个键对应的值都是None(这个我感觉有点多余,既然不指定值,我还定义它干嘛?)
person=dict.fromkeys({'name','sex','age'}) print(person) #运行结果 {'sex': None, 'age': None, 'name': None}
若不想展示 None 可以指定特定的值(真的是特定的值)
person=dict.fromkeys({'name','sex','age'},'特定的值')
print(person)
#运行结果
{'age': '特定的值', 'name': '特定的值', 'sex': '特定的值'}
get:获得字典中某个元素值
person={'name':'张三','sex':'男','age':18,'hobby':['篮球','rap','音乐']}
print(person.get('name'))
#运行结果
张三
get 函数 和之前用到得 dict['name'] 是一样的,既然存在就有他的道理,
案例:访问一个不存在的元素时,看看他们会有什么不同?
正常的情况下:
person={'name':'张三','sex':'男','age':18,'hobby':['篮球','rap','音乐']}
print("person.get('name') 结果为:"+person.get('name'))
print("person['name'] 结果为:"+person['name'])
#运行结果
person.get('name') 结果为:张三
person['name'] 结果为:张三
错误的情况下:...好尴尬,报错了
person={'name':'张三','sex':'男','age':18,'hobby':['篮球','rap','音乐']}
print("person.get('name') 结果为:"+str(person.get('xxx')))
print("person['name'] 结果为:"+str(person['xxx']))
#运行结果?
person.get('name') 结果为:None
#-----------------------------------
Traceback (most recent call last): File "D:/develTools/PycharmProjects/project1/venv/Include/test3.py", line 3, in <module> print("person['name'] 结果为:"+person['xxx']) KeyError: 'xxx'
由此看出,使用 dict['name'] 当name 不存在时,则会抛出异常,dict.get('name') 会抛出Node,若你不想返回Node ,也是可以指定的。如
get('key','异常时消息打印')
person={'name':'张三','sex':'男','age':18,'hobby':['篮球','rap','音乐']}
print("person['name'] 结果为:"+person.get("xxx",'哎呀,你居然找不到'))
#运行结果
person['name'] 结果为:哎呀,你居然找不到
比起上面的报错 ,这样是不是更优雅?正常的情况是不会打印后面的信息的
person={'name':'张三','sex':'男','age':18,'hobby':['篮球','rap','音乐']}
print("person['name'] 结果为:"+person.get("name",'哎呀,你居然找不到'))
#运行结果
person['name'] 结果为:张三
items:返回一个包含所有字典项的列表,每个元素都为(key,value)的形式。但是字典项在列表中的顺序是不确定的?
这里打个问号,我运行了好几遍顺序都是一致的,刚开始我以为数据少,然后还加了一些,无论多少遍还还是一致的。可能书本的python版本比较老吧,新版本已经修复这个问题了(所以不要光看书,实践最重要)。
items 返回值属于一种名为字典试图的特殊类型(我不是很明白,书本是这么说的,只有待以后接触更多python知识才会知晓),字典视图可用于迭代(就是能够遍历,意思是字典本身是不能遍历的?需要转为字典视图?)。
person={'name':'张三','sex':'男','age':18,'hobby':['篮球','rap','音乐'],'sss1':'sss1','sss2':'sss2','sss3':'sss3','sss4':'sss4','sss5':'sss5'}
print(person.items())
#运行结果
dict_items([('name', '张三'), ('sex', '男'), ('age', 18), ('hobby', ['篮球', 'rap', '音乐']), ('sss1', 'sss1'), ('sss2', 'sss2'), ('sss3', 'sss3'), ('sss4', 'sss4'), ('sss5', 'sss5')])
keys:返回一个字典试图(又是字典试图,上面提到的),包含字典中所有的key
person={'name':'张三','sex':'男','age':18,'hobby':['篮球','rap','音乐'],'sss1':'sss1','sss2':'sss2','sss3':'sss3','sss4':'sss4','sss5':'sss5'}
print(person.keys())
#运行结果
dict_keys(['name', 'sex', 'age', 'hobby', 'sss1', 'sss2', 'sss3', 'sss4', 'sss5'])
pop:根据key删除字典中的 key-value,并返回所属key的值
person={'name':'张三','sex':'男','age':18,'hobby':['篮球','rap','音乐'],'sss1':'sss1','sss2':'sss2','sss3':'sss3','sss4':'sss4','sss5':'sss5'}
print(person.pop('sss1'))
print(person)
#运行结果
删除key为sss1后value=:sss1
最终person里的数据结果:{'name': '张三', 'sex': '男', 'age': 18, 'hobby': ['篮球', 'rap', '音乐'], 'sss2': 'sss2', 'sss3': 'sss3', 'sss4': 'sss4', 'sss5': 'sss5'}
popitem:类似于 list.pop, 弹出列表中最后一个元素。如果你要高效的方式逐个删除并处理所有字典项,这个很有用,因为这样无需先获取key列表。
书本上说 popitem 是随机删除 字典中的某个字典项(看到这句话时,我赶紧测试了下,运行几次后,还是没有这个问题),因为字典时没有顺序可言的。书本中也指出了若希望 popitem以可预测的顺序弹出字典项,请阅读collections中的OrderedDict类
person={'name':'张三','sex':'男','age':18,'hobby':['篮球','rap','音乐'],'sss1':'sss1','sss2':'sss2','sss3':'sss3','sss4':'sss4','sss5':'sss5'}
print(person.popitem())
#运行结果
最后一个 字典项:('sss5', 'sss5')
setdefault:这个很有意思,他的功能和 get函数类似。
但是setdefault是具备添加功能的, 当字典中存在时,setdefault 返回 字典中 该key的value
person={'name':'张三','sex':'男','age':18,'hobby':['篮球','rap','音乐']}
print(person.setdefault('name'))
#运行结果
张三
但是当key不存在时,他会将这个字典项存入 字典中( value默认为 None),为了证明 setdefault函数 将 xxx 存入 到 person中。这里用 person['xxx'] 的形式获取 该 xxx 的值
person={'name':'张三','sex':'男','age':18,'hobby':['篮球','rap','音乐']}
print(person.setdefault('xxx'))
#为了证明 setdefault函数 将 xxx 存入 到 person中。这里用 person['xxx'] 的形式获取 该 xxx 的值
print(person['xxx'])
#运行结果
None
None
value 也是可以指定的
person={'name':'张三','sex':'男','age':18,'hobby':['篮球','rap','音乐']}
print(person.setdefault('xxx','N/A'))
#为了证明 setdefault函数 将 xxx 存入 到 person中。这里用 person['xxx'] 的形式获取 该 xxx 的值
print(person['xxx'])
#运行结果
N/A
N/A
update:使用一个字典中的项更新另一个字典
注意:不要key重复
person={'name':'张三','sex':'男','age':18,'hobby':['篮球','rap','音乐']}
school={'school':'xxx希望小学','className':'一年级一班'}
person.update(school)
print(person)
#运行结果
{'name': '张三', 'sex': '男', 'age': 18, 'hobby': ['篮球', 'rap', '音乐'], 'school': 'xxx希望小学', 'className': '一年级一班'}
values:返回一个由字典中的值所组成的字典试图
不同于keys函数,values 是可以包含重复的。
案例:张三的年龄我为18,考试得分也是18
person={'name':'张三','sex':'男','age':18,'hobby':['篮球','rap','音乐'],'score':18}
print(person.values())
#运行结果
dict_values(['张三', '男', 18, ['篮球', 'rap', '音乐'], 18])
笔后语录:
目前为止,python教学视频进度一点没变,还是在面向对象(深入面向对象)部分,下部分该学习 包相关的知识了(我觉得不应该急着去看视频)。但是我停下来了,买了一本python基础书,从头开始看python,书本内容我也看到面向对象,这篇博客园这也是第四章的全部内容。我目前博客里所有有关python的文章都是按照书本中的知识案例点来总结的。所有的案例也是我一个个敲出来贴到博客中。有些时候我按照书本中的案例运行时,我也会产生一些其他想法,我就会尝试另外一种运行方式,并将结果写到博客中。我写这些博客的目的不是为了装X,我觉得完全没必要,我本身是从事java开发的工作,学习python也只是我闲暇的时光去学习(主要是太多人学习,我觉得多多少少要接触一点)。这个行业压力太大了,随时觉得自己要被淘汰。
那我又干嘛写呢?本身就没打算靠python挣钱吃饭,大部分时间还是关注到java中比较多,所以学完长时间不用,就很容易忘,好记性,不如烂笔头。把学习的过程记录下来,主要是加强记忆,然后学习完某种技术后,再回头看看自己的博客真的有种成就感。以前我不懂写博客(内容没有营养,杂乱无章),翻看我以前博客(跟屎一样)没有归类,没有系统化,所以以后的博客内容尽量让它丰富起来。
突然谈到写博客,是因为,我害怕的我的内容误导你,不过请放心,所有代码我都是经过测试了的。以后接触到更多知识后,我会补充到相对应的博客中,不仅仅是python。
要是内容有什么不对,请下方留言。

浙公网安备 33010602011771号