5. Python3教程丨应996而生的托儿所故事:长相奇特的Dict(字典)

Dict(字典)

1 年级 1 班迎来了第一次期中考试,班主任桃老师想把他们的姓名和成绩都记录到一个文件里。可是我们之前讲的 List Tuple 都不能比较好的实现这个功能,所以这一节我们就引入了 Dict(字典) 这个东西。

标志

这是一个乍看起来结构和名字都有些奇怪的数据类型,我们先来看看 字典 这位老哥长啥样,以及有什么样的性格:

>>> a = {'a':1, 'b':2, 'c':3}

我们会发现字典的总体特征就是: Dict = {key:value } ,即内部所有元素都包含在大括号 {} 之下,内部都是有一个 key(键) 和一个 Value(值) 构成的。

特征

近期996制度在国内的扩散,家长们的压力越来越大。1年级1班旁边迎势开了一家帮家长接孩子放学的托儿所,叫做 wecare 。这缓解了很多上着班要请假接孩子放学,再回去继续上班的家长们的不少压力。

托儿所为了让家长们放心,给每位小朋友都安排了一位老师单独接送,并且这位老师永远只会照顾这一个孩子。更让人安心的是,外界的别人没法直接接触到孩子,别人只能通过这个老师才能接到孩子

每位老师的名字我们用 key(键) 来表示,每位小朋友的名字我们用 value(值) 来记录,每位老师和小朋友组成一对小搭档即 老师的名字 : 小朋友的名字 ,我们叫做 键值对 ,这就是这家托儿所的基本情况。

创建

托儿所第一天营业便接到了三位家长的委托,分别是父母忙于做服装外贸的 ‘王有才’ 小朋友的家长、父母都是程序员却受制于996没法接孩子的 ‘李布尔’ 小朋友的家长,以及教师父母临时出差听课的 ‘郑仕’ 小朋友的家长。

根据家长的了解后,他们分别选择了 ‘金老师’ ‘冯老师’ 以及 ‘严老师’ 。托儿所老师根据家长们的意见,最终用 dict = {} 的方式创建了一个关于小搭档们的字典

>>> wecare = {'金老师':'王有才', '冯老师':'李布尔', '严老师':'郑仕'}

访问

第一种方式: 托儿所名[老师的名字]

托儿所为了确定无误,又赶紧 托儿所名[老师的名字] 的方式访问了一下字典内的元素,比如想看看 ‘金老师’ 照顾的哪位同学:

>>> wecare = {'金老师':'王有才', '冯老师':'李布尔', '严老师':'郑仕'}
>>> wecare['金老师']
'王有才'

第二种方式: 字典名.items()

这种方式不是访问某个键对应的值,而是将返回一个完整的列表,列表内将以元组的形式显示出所有可遍历的键值对。听着有点绕吗?那我们先来看看结果:

>>> wecare = {'金老师':'王有才', '冯老师':'李布尔', '严老师':'郑仕'}
>>> wecare.items()
dict_items([('金老师', '王有才'), ('冯老师', '李布尔'), ('严老师', '郑仕')])

我们看到,首先在 dict_items() 这个结果里面的是一个完整的列表 dict = { [咱们先不管里面有啥] } ,这里可以知道的是 字典名.items() 返回的结果是一个列表。

然后在那个返回的列表 [] 里面的是好多个元组即 [ (),(),() ] ,这些元组们其实就是原来的键值对们,这样应该就好理解点了吧,为了表述清晰还是用图例来看一下吧:
在这里插入图片描述

完美,托儿所开始正式运营。

修改

后来有一天,父母都是996制度下程序员的小朋友 ‘李布尔’ 改名为 ‘李康怡’ ,父母现在觉得人最重要的事情应该是健康与快乐,他们希望孩子可以在一个这样的环境中成长。

托儿所老师 托儿所名[老师姓名] = 孩子姓名 的方式重新定义了一遍那个键值对

>>> wecare['冯老师'] = '李康怡'
>>> wecare
 {'金老师':'王有才', '冯老师':'李康怡', '严老师':'郑仕'}

我们也从这里发现:在字典中每个 key(键) 只允许存在一次,若出现两次则自动视为更新前一个 键值对 以最后一次定义为准:

>>> wecare = {'金老师':'王有才', '冯老师':'李布尔', '严老师':'郑仕', '冯老师':'李康怡'}
>>> print(wecare)
 {'金老师':'王有才', '冯老师':'李康怡', '严老师':'郑仕'}

通过观察我们又可以发现:

在同一个字典中,若出现两次完全一致的key(键),则第二次key(键)对应的value2(值)将会代替掉第一次key(键)对应的value1(值)。并且是直接在原键值对上修改,顺序并不会发生变化。

检验

第一种:用 key in 字典 或者 key not in 字典 的方式

托儿所的负责人刘老师有时会检查每位老师是否按时到岗,会用 key(键)in 字典名 的方式检验:

>>> wecare = {'金老师':'王有才', '冯老师':'李康怡', '严老师':'郑仕'}
>>> '金老师' in wecare
True

要注意的是:在字典中 in/not in 字典名 的用法只能检查键是否存在于字典中,而不能检查值是否在字典中:

>>> wecare = {'金老师':'王有才', '冯老师':'李康怡', '严老师':'郑仕'}
>>> '李康怡' not in wecare
True

第二种:用 字典名.get(要检查的键,若检查不到前面的键要输出的默认字) 的方式

>>> wecare = {'金老师':'王有才', '冯老师':'李康怡', '严老师':'郑仕'}
>>> wecare.get('赵老师','对不起,检索不到这位老师!')
'对不起,检索不到这位老师!'

三种复制

就像在《3. Python3教程丨一个故事看懂List所有用法:1年级1班的班级生活》这一篇讲的一样,字典和列表都存在三种复制,即: 直接赋值 浅拷贝 深拷贝 三种。负责人刘老师也想给这份名单贝备份一下,保险起见就将三种方式都尝试了一遍:

以下解释方式和上文完全一致,对三种复制已经理解的可以直接跳过 三种复制 看下文

刘老师想把这个名单拷贝一份,留在他的备份 Beifen 里,开始纠结起来了:列表(list)的备份方式有 直接赋值 浅拷贝 深拷贝 三种,这种情况下用哪种好呢?都试试吧!

**第一种拷贝:直接赋值

一开始老师想偷偷懒:直接把 wecare 字典赋值给我的备份文件 Beifen 不就好了 !于是她尝试了直接赋值的方式:

>>> wecare = {'金老师':'王有才', '冯老师':'李康怡', '严老师':'郑仕'}
>>> Beifei = wecare
>>> Beifei
 {'金老师':'王有才', '冯老师':'李康怡', '严老师':'郑仕'}

完美!可是直到有一天,老师发现他办公室里的那份 Beifen 文件里,怎么 ‘郑仕’ 自己变成了 ‘郑士’ ?他去问1年级1班的班主任,班主任告诉他:

郑仕改名了,我就把我手里的班级名单改了,怎么,您那儿的列表也变了?

是的,也改变了。

>>> wecare['严老师'] = '郑士'
>>> wecare
{'金老师':'王有才', '冯老师':'李康怡', '严老师':'郑士'}
>>> Beifei
wecare = {'金老师':'王有才', '冯老师':'李康怡', '严老师':'郑士'}

托儿所老师想这倒是方便,但是这不靠谱啊,这样我办公室文件就可以让提交人随便改了!

于是老师只能开始尝试第二种:

**第二种拷贝:浅拷贝

浅拷贝的使用方式主要有 拷贝到的地方 = 原字典.copy() 拷贝到的地方 = 原字典[:] 拷贝到的地方 = dict(原字典) 效果相同的三种,教导主任就以第一种为例试一下:

>>> Beifei = wecare.copy()
>>> Beifei
wecare = {'金老师':'王有才', '冯老师':'李康怡', '严老师':'郑仕'}

好像看起来又成功了,但老师不死心。让班主任再改一下他手里的班级文件,看看自己这里会不会变:

>>> wecare['严老师'] = '郑士'
>>> wecare
{'金老师':'王有才', '冯老师':'李康怡', '严老师':'郑士'}
>>> Beifei
wecare = {'金老师':'王有才', '冯老师':'李康怡', '严老师':'郑士'}

还是会变! 刘老师又放弃了第二种拷贝方式,将希望放在了最后一种上:

**第三种拷贝:深拷贝

深拷贝和刚才两种都不一样,使用深拷贝前需要先用 import 语句将 copy 调用出来,方法为 import copy 。调用后,深拷贝的使用方法为 拷贝到的地方 = copy.deepcopy(原字典名)

>>> import copy
>>> Beifei = copy.deepcopy(wecare)
>>> Beifei
{'金老师':'王有才', '冯老师':'李康怡', '严老师':'郑仕'}

失败了两次的负责人刘老师这时候已经不信结果了,执意要班主任再在他那改一次名字:

>>> wecare['严老师'] = '郑士'
>>> wecare
{'金老师':'王有才', '冯老师':'李康怡', '严老师':'郑士'}
>>> Beifei
wecare = {'金老师':'王有才', '冯老师':'李康怡', '严老师':'郑仕'}

成功了!这时候我们就明白了:在深拷贝中,当改变原序列中二层以及二层以下的内容时,拷贝后的内容不会受到任何影响。而直接赋值和浅拷贝的方式会受影响。

啥叫二层?

#这叫只有一层:
first = []
#这叫二层,存在列表嵌套
second = [[],[]]

删除

过去了几天, ‘郑士’ 小朋友的家长们从外地听课回来了,家长带着他来班里了离所手续。从此 ‘严老师’ 可是暂时休息一段时间了,于是负责人刘老师要将严老师从名单中暂时删除:

第一种方式: del 托儿所名 [老师姓名]

我们可以用 del 托儿所名[老师姓名] 的方式删除掉指定的老师姓名以及他带的学生,即删除掉指定key所代表的那个键值对

>>> wecare =  {'金老师':'王有才', '冯老师':'李康怡', '严老师':'郑士'}
>>> del wecare['严老师']
wecare
 {'金老师':'王有才', '冯老师':'李康怡'}

第二种方式: 托儿所名.pop(老师姓名,若不存在这个老师要返回的默认字)

这种方式更像是一种检验性的删除,如果指定的这个键存在则会删除掉key所在的那个键值对,如果指定的键不存在则会返回一个提前指定好的默认值

例如我们想删除一个叫 ‘孙老师’ 的人,如果孙老师确实在字典名单里则会直接删除,如果字典中不存在这个人,我们想返回一个语句告诉我们这个老师不存在:

>>> wecare =  {'金老师':'王有才', '冯老师':'李康怡', '严老师':'郑士'}
>>> wecare.pop('孙老师','对不起,没有这位老师的名字!')
'对不起,没有这位老师的名字!'

计数

我们再来用 len(托儿所名) 的方式计一下数,确定一下目前还有几位老师在负责照顾每天小朋友的接送:

>>> wecare =  {'金老师':'王有才', '冯老师':'李康怡'}
>>> len(wecare)
2

还有 ‘金老师’ ‘冯老师’ 继续工作,我们也因此得知:在字典中,len的计数是以key(键)的数量为准的。

提取字典内所有key

快到月底了,托儿所的负责人刘老师准备把托儿所目前所有在聘老师的名单做成一个列表。刘老师用 托儿所名字.keys() 的方式提取出了所有的key:

>>> wecare =  {'金老师':'王有才', '冯老师':'李康怡', '严老师':'郑士'}
>>> wecare_name = icare.keys()
>>> wecare_name
dict_keys(['金老师', '冯老师', '严老师'])

这样结果已经出来了,但是我们发现这返回的结果不是列表呀:

>>> type(wecare_name)
<class 'dict_keys'>

刘老师突然想起来有一种方式可以将其他序列类型转化为列表, 她尝试了一下 list() 这种方式:

>>> wecare =  {'金老师':'王有才', '冯老师':'李康怡', '严老师':'郑士'}
>>> wecare_name = list(wecare.keys())
>>> wecare_name
['金老师', '冯老师', '严老师']

这样,老师们的名字就已经从字典中提取出来了。

提取字典内所有value

当然不仅是字典中的key可以提取,value也是同样可以提取的,方法为 字典名.values()

>>> wecare =  {'金老师':'王有才', '冯老师':'李康怡', '严老师':'郑士'}
>>> wecare.values()
dict_values(['王有才', '李康怡', '郑士'])

同样,我们可以用刚才 list() 的方式把这个结果以list的形式赋给一个新列表:

>>> wecare =  {'金老师':'王有才', '冯老师':'李康怡', '严老师':'郑士'}
>>> wecare_kid = list(icare.values())
['王有才', '李康怡', '郑士']

以某列表的元素为键创建字典

终于到了月底,托儿所负责人刘老师要给几位托儿所老师发工资了,刘老师拿出了前几天创建好的一个包含老师姓名的列表:

>>> wecare_name = ['金老师','冯老师','严老师']

托儿所负责人用 dict.fromkeys(列表名) 的方式,将上面列表中的所有元素都作为一个key传入了新字典:

>>> wages = dict.fromkeys(wecare_name)
>>> wages
{'金老师': None, '冯老师': None, '严老师': None}

我们发现列表 wecare_name 里面所有的元素这时候都已经成为了字典 wages 里的key,但是这些key没有对应的value值,都为 None。这时候我们要给老师们发工资了,因为都是当时说好的 3,000元 / 月 ,所以我们可以使用 dict.fromkeys(列报名,统一的值) 的方式:

这样一个工资表的字典就创建完成了!

>>> wages = dict.fromkeys(wecare_name,3000)
>>> wages
{'金老师': 3000, '冯老师': 3000, '严老师': 3000}

检验键与添加

第一种方式:用 字典名.setdefault(键,默认值) 检查键并添加

看着工资单的刘老师突然感觉有什么不对:

我的工资是不是没写进去!!!

于是刘老师用 托儿所名.setdefault(要检查的键,若没有该键则创建一个并赋予这个默认值) 的方式赶紧操作了一下:

>>> wages = {'金老师': 3000, '冯老师': 3000, '严老师': 3000}
>>> wages.setdefault('刘老师',3500)
>>> wages
{'金老师': 3000, '冯老师': 3000, '严老师': 3000, '刘老师': 3500}

我们发现,如果检查的这个键本身不存在,那么就会将这个键添加到字典中,将提前设置好的默认值给键,同时结果会把那个默认数输出。

刘老师看到输出了一个默认值,恍然大悟:

我真的没把自己写进去!!!

第二种方式:用 字典名.update(另一个字典名) 直接添加

还有一种方式,就是刘老师将自己的名字和工资创建一个字典,然后将这个字典以 字典名.update(另一个字典名) 的方式更新到原工资字典中:

>>> wages = {'金老师': 3000, '冯老师': 3000, '严老师': 3000, '刘老师': 3500}
>>> wochadianmeigongzi = {'刘老师':3500}
>>> wages.update(wochadianmeigongzi)
>>> wages
{'金老师': 3000, '冯老师': 3000, '严老师': 3000, '刘老师': 3500}

可见这种方式可以将一个字典直接添加到另一个字典中。

清空

996.ICU事件过去很久后,互联网产业又经历了关于员工健康主题的几次全国大规模线上下形式的抗议, 国内绝大多数企业妥协取消了996工作制。 ‘李康怡’ 小朋友的父母也终于能每天下班接上孩子一家人开心的吃顿晚饭,聊聊彼此的一天; ‘王有才’ 的父母也开始在企业放权,重新将生活的重心放到了孩子与家庭上面。托儿所面临解散,老师们也清除了原有的字典列表:

第一种方式: 托儿所名.clear()

这一种方式会将字典内部所有键值对清空,使字典变为一个空字典:

>>> wecare =  {'金老师':'王有才', '冯老师':'李康怡'}
>>> wecare.clear()
>>> wecare
{}

第二种方式: del 托儿所班名

这一种方式会直接删除掉整个字典:


>>> wecare =  {'金老师':'王有才', '冯老师':'李康怡'}
>>> del wecare
>>> wecare
NameError: name 'wecare' is not defined

当我们用 del 托儿所名 的方式将字典清空后,再尝试打印内容就会报错:

name ‘wecare’ is not defined.

第三种方式: 托儿所名.popitem()

这是一个比较佛系的删除方式,使用方法就是如小题目所示: **托儿所名.popitem() 。执行了这个操作后,python会随机删除一对键值对,并将删除的键和值以元组的形式作为结果返回出来:

>>> wecare =  {'金老师':'王有才', '冯老师':'李康怡'}
>>> wecare.popitem()
('冯老师', '李康怡')
>>> type(wecare.popitem())
<class 'tuple'>

此时托儿所只有两对搭档,所以执行两遍即可清除掉字典内所有的键值对了:

>>> wecare =  {'金老师':'王有才', '冯老师':'李康怡'}
>>> wecare.popitem()
('冯老师', '李康怡')
>>> wecare.popitem()
('金老师', '王有才')
>>> wecare
{}

托儿所一班就像从来没存在过一样,再也找不到了。这似乎是一件值得庆幸的事情,不过那几位临时雇佣的托儿所老师也因此失去了工作。人们又重新回到了原有的生活中去,而资本仍在默默流淌。

以上剧情均为虚构,如有雷同,不胜欣慰:

'''
“你的眼睛 像颗水晶通透,
里面有一个无穷无尽的宇宙。
小小的你 在你小小的梦里,
把我所有大大的事情都吹进风里。
我为我将对你撒的谎先跟你道歉,
当你发现黑白不是那么的分明。
世界不是那么的公平,
别太失望 我讲的是个梦想。
             ——陈奕迅《babysong》”
'''
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值