为什么要使用字典
引出字典
当一系列的值组合成数据结构,并通过编号
来访问各个值的时候,可以使用列表。而在另外一种情况下,例如当我们不想使用通过编号
来访问其值的数据结构,而是想用一种通过名称
来访问其值的数据结构,这种数据结构就称为映射(mapping)
。在Python中,字典(dict)
是唯一的内置映射类型
,其值不按顺序排列,而是储存在键
下,这个键
可以是数字、字符串或元组。
字典的用途
从字典这个名称来看,它的功能就是在于找到某个特定的单词(在Python的字典数据结构中,这个单词叫键key
),从而获得其定义(Python中叫值
)。
我们来看一个案例,例如我们有以下的名单:
|
|
如果我们要创建一个小数据库来储存这些人的电话号码,如何实现?在学习字典这个数据结构前,我们可能会想到使用列表,创建一个列表储存他们的电话号码,如下所示:
|
|
当我们要查询Ceil
的电话号码时,可以按下面的代码实现:
|
|
完整的运行结果如下所示:
|
|
但是这种方法比较麻烦,事实上,如果我们直接按照姓名来查找电话号码就方便了,如下所示:
|
|
运行结果如下所示:
|
|
其中phonebook
这个变量的类型就是字典
。
字典的定义
字典包括一系列的索引,不过就已经不叫索引了,而是叫键,然后还对应着一个值,叫键值。每个键对应着各自的一个单独的键值。这种键和键值的对应关系也叫键值对,有时候也叫项。其中,“键:值”元素的无序可变序列,字典中的每个元素包括“键”和“值”两部分,表示一种映射或对应关系,也称为关联数组。定义字典时,每个元素的“键”和“值”用冒号分隔,不同元素之间用逗号分隔,所有的元素放在一对大括号中。字典就像是一个列表一样,但更加泛化了,是列表概念的推广。在列表里面,索引必须是整数;而在字典里面,你可以用几乎任何类型来做索引了。用数学语言来说,一个字典就代表了从键到键值的一种映射关系,所以你也可以说每个键映射到一个键值。举例来说,我们可以建立一个从英语单词映射到西班牙语单词的字典,这样键和简直就都是字符串了。
建立字典
使用dict()函数
dict这个函数创建一个没有项目的空字典,如下所示:
|
|
其中,大括号代表了一个空字典,要在字典里添加项(项是指字典的键与值的对应关系,也叫键值对),可以使用方括号,如下所示:
|
|
也可以采用直接给定的“键:值”来创建字典,如下所示:
|
|
通过dict转化为字典
如下所示:
|
|
运行结果如下所示:
|
|
通过fromkeys()
创建新字典
给定内容为“键”,创建“值”为空的字典:
|
|
运行结果如下所示:
|
|
fromkeys()
方法用于创建一个新的字典,并以可迭代对象中的元素分别作为字典中的键,且所有键对应同一个值,默认为None。
如果不想使用默认值None,那么可以指定值,如下所示:
|
|
结果如下所示:
|
|
字典的修改
当以指定“键”为下标,并为字典元素赋值时,有两种含义:①若该“键”存在,则表示修改该“键”对应的值;②若该键不存在,则表示添加一个新的“键:值”,也就是添加一个新元素,如下所示:
|
|
添加字典——更新字典update()
update()方法可以将另一个字典的“键:值”一次性全部添加到当前的字典对象,如果两个字典中存在相同的“键”,则以另外一个字典中的“值”为准对当前字典进行更新,如下所示:
|
|
删除字典del()
del可以删除整个字典,也可以删除字典中指定的元素,如下所示:
|
|
删除字典pop()
和popitem()
(1)pop()
方法删除字典给定键 key 所对应的值,返回值为被删除的值。key值必须给出。 否则,返回default值。
(2)popitem()
方法随机返回并删除字典中的一对键和值(一般删除末尾对)。
如果字典已经为空,却调用了此方法,就报出KeyError异常,如下所示:
|
|
随机删除字典元素dd.popitem()
dd.popitem()
的功能是随机删除字典中的一个元素,并将所删除的值返回,运行结果如下所示:
|
|
字典的清除clear()
字典的清除使用clear()方法,如下所示:
|
|
清除与删除是两种不同的操作,如下所示:
|
|
访问项(键:值)
字典中的项没有顺序,因此也没有索引,但可以通过键来直接查找键值,如下所示:
|
|
字典的”键(key)”不能是可变类型,也就是说不能是列表,但可以是元组,整数,字符串。
访问值get()
get()函数用法:get() 函数返回指定键的值,如果值不在字典中返回默认值。
|
|
访问值setdefault()
此方法用于返回指定“键”对应的“值”,如果字典中不存在该“键”,就添加一个新元素,并设置该键对应的值,如下所示:
|
|
访问值遍历字典item()
对字典对象进行迭代时,默认是遍历字典的键,如果使用items()方法返回字典中的元素,即所有的项(项这里是指“键:值”对)。字典对象的keys()方法返回所有的值,如下所示:
|
|
同置函数对字典的处理
内置函数len(),max(),min(),sum(),sorted()以及成员测试运算符in也适用于字典对象,但默认作用于字典的“键”,若想作用于元素,即“键:值”对,则需要使用字典的对象items()方法,若作用于“值”,则需要使用valules()方法。
案例实战:字典应用
案例实战:字典应用
下面的一段代码会生成包括1000个随机字符的字符串,然后统计每具字符的出现次数。
包解释:
string:String
模块包含许多有用的常量和类,以及一些不推荐的遗留函数,这些函数也可以作为字符串上的方法使用。此外,Python的内置字符串类支持序列类型(str、Unicode、list、tuple、byteArray、Buffer、xrange)中描述的序列类型方法,以及String方法部分中描述的特定字符串的方法。若要输出格式化字符串,可以使用模板字符串或字符串格式操作部分的%运算符。另外,有关基于正则表达式的字符串函数,请参见re模块。random:
这个模块是用于实现各种分页的伪随机数生成器。对于整数来说,它可以从一个范围内进行均匀选择,对于序列来说,此模块中的有可以均匀选择一个元素的函数,以及生成一个随机排列的列表的耿发,以及用于不放回抽样的函数。
代码解释:
ascii_letters
是生成所有字母,从a-z和A-Zdigits
是生成所有数字0-9.punctuation
生成标点符号random.choice
随机选择一个元素
第1种方案:最常规的实现方法
代码如下所示:
|
|
运行结果如下所示:
|
|
第2种方案:上述代码可以更改为:
|
|
运行结果如下所示:
|
|
第3种方案:
|
|
运行结果如下所示:
|
|
字典排序sort()
内置函数sorted()可以对字典元素进行排序并返回新列表,充分利用key参数可以实现丰富的排序功能,如下所示:
|
|
提取字典的子集
|
|
提取字典中的某个键的值d.get()
如果此键不在字典中,就会返回none。
|
|
计算字典的健值
|
|
字典的翻转
|
|
字典推导式
字典推导和列表推导的使用方法是类似的,只不中括号该改成大括号。直接举例说明:
案例1:大小写key合并
|
|
案例2:快速更换key和value
|
|
使用字典推导式生成符合特定条件的字典
|
|
再看一个案例,在这个案例中,寻找得到分最高的同学:
|
|
使用字典推导式提取字典的键与值
|
|
注1:其中用到了enumerate(),这是python的内置函数、在字典上是枚举、列举的意思,它可以遍历/可迭代的对象(如列表、字符串),enumerate多用于在for循环中得到计数,利用它可以同时获得索引和值,即需要index和value值的时候可以使用enumerate。
注2:如果不用for循环,enumerate()返回的是一个enumerate对象,如下所示:
|
|
查看字典元素的数目len()
使用len()函数,如下所示:
|
|
字典的复制
字典中复制的方法有两种,分别是浅复制(copy
)与深复制(deepcopy
)。
字典的浅复制copy()
如果直接用=
复制字典,其实是为同一个对象贴了两个标签,如下所示:
|
|
运行结果如下所示,可以发现,a与d的id是一样的,它们表示的是同一个对象,如果用copy方法来进行复制,如下所示:
|
|
从运行结果中我们可以看到这些信息:
- 我们使用了字典的浅复制方法
copy()
,生成了一个y
变量,开始的时候,y
与x
的内容是一样的; - 接着我们在
x
中替换掉了username
这个键的值,用mlh
替换了admin
,但y
中的username
的值并不改变,还是username
; - 我们在
y
中删除了machines
这个键对应值的bar
,同时x
中machines
这个键对应的值也发生了变化。
这就是浅复制的特点,下面介绍深复制(deepcopy()
)。
字典的深复制deepcopy()
还是以上面的案例为例说明一下,如下所示:
|
|
运行结果如下所示:
|
|
从结果来看,可以得到以下信息 :
x
与y
之间并无影响;- 进行浅复制的时候,语法是
y = x.copy()
,这是一种方法
,而进行深复制的时候,语法是y = deepcopy(x)
,这是一个函数
。
参考资料
- MagnusLieHetland. Python基础教程.第3版[M]. 人民邮电出版社, 2018.