本课介绍Python的映射类型——字典,课中会讨论字典中的映射关系,字典的声明、赋值及其相关运算。通过本课的学习,将会掌握映射类型及字典的使用方法。
映射关系
映射是指两个事物之间的对应关系,两个事物间的映射关系在我们生活中大量存在。例如,公民身份证号对应唯一的一个公民、公司内的员工编号对应唯一的一个员工,类似身份证和公民、员工编号和员工的这种对应关系就是映射中的一对一关系。

除了一对一关系外,映射也有一对多关系。例如,一个人的身份证号可能对应多张银行卡、同一个姓名可能会对应多个人。当具有一对多关系的多个事物出现交集时,就要考虑去重机制。例如,当一个单位有重名的员工时,为了区分重名的员工,可能就会在重名员工的姓名前加上其它可区分的词语。

字典
Python也提供了映射类型,字典是Python语言中唯一的映射类型。字典有两个属性,一个属性是key(也称为键),一个属性是value(也称为值),key和value统称为键值对,一个key可以对应一个值,也可以对应多个值。通过key可以获取到value。例如,可以把学生编号和姓名以字典方式存储起来,学生编号存储到key中,学生姓名存储到value中。这样就可以通过学生编号很容易找到某位学生了。


创建一个字典对象,需要使用{}括起来,字典中元素都在{}括号内,字典中的键值对key和value用英文冒号分隔,键值对之间用英文逗号分隔。一个键值对中key必须唯一。value可以有多个值。值可以取任何数据类型,但key必须是不可变的类型,如字符串、元组、数字等类型。

案例代码:
>>> #键为字符串的字典
>>> a = {"0001":"张**","0002":"王**","0003":"李**"}
>>> print(a)
{'0001': '张**', '0002': '王**', '0003': '李**'}
>>> #键为数值的字典
>>> b = {1:"张**",2:"王**",3:"李**"}
>>> print(b)
{1: '张**', 2: '王**', 3: '李**'}
>>> #值为列表的字典
>>> c = {"合格":["张**","王**","李**"]}
>>> print(c)
字典对象也可以通过Python的内置函数dict来创建,dict有三个函数声明。
1、class dict(**kwarg)
参数**kwarg是可选参数,如果没有给出**kwarg,会创建一个空字典。**表示可以传入多个参数,传入的参数会被转换为字典元素。传入的参数为如下形式:
dict(参数名称=参数值,……,参数名称=参数值)
案例代码:
>>> dic = dict(one='1', two='2',three='3')
>>> print(dic)
{'one': '1', 'two': '2', 'three': '3'}
2、class dict(mapping, **kwarg)
参数mapping是一个映射函数,如Python的内置函数zip、map。该映射函数将返回一个元组的迭代器,其中的第 i 个元组包含来自每个参数序列或可迭代对象的第 i 个元素,函数会以该元组的迭代器创建字典对象。如果给出了**kwarg,则该参数的参数名称和值会附加到已创建的字典对象中。
案例代码:
>>> dic = dict(zip(['one', 'two', 'three'], [1, 2, 3]),four='4')
>>> print(dic)
{'one': 1, 'two': 2, 'three': 3, 'four': '4'}
>>>
3、class dict(iterable, **kwarg)
参数iterable是一个可迭代对象,该可迭代对象中的每一项本身必须为一个刚好包含两个元素的可迭代对象。每一项中的第一个对象将成为新字典的一个键,第二个对象将成为其对应的值。如果一个键出现一次以上,该键的最后一个值将成为其在新字典中对应的值。如果给出了**kwarg,则该参数的参数名称和值会附加到已创建的字典对象中。
案例代码:
>>> d = dict([('two', 2), ('one', 1), ('three', 3)],four='4')
>>> print(d)
{'two': 2, 'one': 1, 'three': 3, 'four': '4'}
>>>
字典类型提供了一个fromkeys()静态方法,该方法也可以创建一个字典对象,用该方法创建的字典的key都对应相同的值。
fromkeys()需要传入两个参数,第一个参数指定key,第二个参数为字典所有key对应的初始值。
案例代码:
>>> #声明一个列表,列表内容为待创建字典的键
>>> seq = ('0001', '0002', '0003')
>>> # 创建无默认值的字典
>>> student = dict.fromkeys(seq)
>>> print("字典为 : %s" % str(student))
字典为 : {'0001': None, '0002': None, '0003': None}
>>> # 创建有默认值的字典
>>> student1 = dict.fromkeys(seq,"姓名待输入")
>>> print("字典为 : %s" % str(student1))
字典为 : {'0001': '姓名待输入', '0002': '姓名待输入', '0003': '姓名待输入'}
>>>
字典操作方法
下面的表格列出了字典支持的操作,表中d是指字典对象,key是指字典对象元素的key,value是指字典对象元素的value。

注释
(1)list是Python内置函数,返回字典d中使用的所有键的列表。
案例代码:
>>> d = {"one":1,"two":2,"three":3}
>>> key = list(d)
>>> print(key)
['one', 'two', 'three']
>>>
(2)len是Python内置函数,返回字典d中的项数。
案例代码:
>>> d = {"one":1,"two":2,"three":3}
>>> print(len(d))
3
>>>
(3)d[key]是访问字典元素的运算符,运算符返回 d 中以 key 为键的值,如果字典中不存在 key 则会引发 KeyError异常。
案例代码:
>>> d = {"one":1,"two":2,"three":3}
>>> print(d["one"])
1
>>> print(d["three"])
3
>>>
(4)d[key]=value是赋值语句,该语句将字典d中的key对应的值设置为value。
案例代码:
>>> d = {"one":1,"two":2,"three":3}
>>> d["one"] = 10
>>> print(d["one"])
10
>>>
(5)del d[key]是删除语句,该语句将字典d中的key键值对删除。
>>> d = {"one":1,"two":2,"three":3}
>>> del d["one"]
>>> print(d)
{'two': 2, 'three': 3}
>>>
下表列出了字典对象元素的视图及更新操作:

注释
(1)iter是Python的内置函数,返回字典d的迭代器。
案例代码:
>>> d = {"one":1,"two":2,"three":3}
>>> k = iter(d)
>>> type(k)
<class 'dict_keyiterator'>
>>>
(2)clear()是字典类型的方法,该方法移除字典对象的所有项。
案例代码:
>>> d = {"one":1,"two":2,"three":3}
>>> d.clear()
>>> print(d)
{}
>>>
(3)get(key[, default])是字典类型的方法,该方法获取字典对象中key对应的值,如果字典对象中没有对应的key,返回default,若default没有给出,返回None。
案例代码:
>>> d = {"one":1,"two":2,"three":3}
>>> print(d.get("one"))
1
>>> d.get("four",4)
4
>>> d.get("four")
>>>
(4)items()是字典对象的方法,该方法返回由字典项 ((键, 值) 对) 组成的一个字典视图。
关于字典视图
由 dict.keys(), dict.values() 和 dict.items() 所返回的对象是字典视图对象。 该对象提供字典条目的一个动态视图,这意味着当字典改变时,视图也会相应改变。
字典视图可以被迭代以产生与其对应的数据,Python的内置函数len返回字典视图的项数,内置函数iter返回字典视图的迭代器,用返回的迭代器可以遍历字典视图的所有元素。
字典视图也可以使用成员操作符in,来判断键、值或项(键值对)是否在字典视图内。可以使用内置函数reversed来返回一个逆序获取字典键、值或项的迭代器。
案例代码:
>>> d = {"one":1,"two":2,"three":3}
# 获取字典对象键值对视图
>>> v = d.items()
>>> type(v)
<class 'dict_items'>
# 从视图中获取迭代器
>>> k = iter(v)
>>> type(k)
<class 'dict_itemiterator'>
# 获取视图的下一项
>>> print(next(k))
('one', 1)
>>>
(5)keys()是字典对象的方法,该方法返回由字典键组成的一个字典视图。
案例代码:
>>> d = {"one":1,"two":2,"three":3}
>>> v = d.keys()
>>> k = iter(v)
>>> print(next(k))
one
>>>
(6)values ()是字典对象的方法,该方法返回由字典值组成的一个字典视图。
案例代码:
>>> d = {"one":1,"two":2,"three":3}
>>> v = d.values()
>>> k = iter(v)
>>> print(next(k))
1
(7)pop(key[, default])是字典对象的方法,该方法从字典对象中移除key,并返回key对应的值。如果字典中没有key,返回default,default是可选参数。
案例代码:
>>> d = {"one":1,"two":2,"three":3}
>>> print(d.pop("one"))
1
>>> print(d)
{'two': 2, 'three': 3}
(8)popitem()是字典对象的方法,从字典中移除并返回一个 (键, 值) 对,键值对会按 LIFO 的顺序被返回。LIFO顺序是后进先出,可以理解为移除字典对象的最后一项。
案例代码:
>>> d = {"one":1,"two":2,"three":3}
>>> print(d.popitem())
('three', 3)
>>> print(d)
{'one': 1, 'two': 2}
>>>

注释
(1)reversed是内置函数,返回一个逆序获取字典键的迭代器。
案例代码:
>>> d = {"one":1,"two":2,"three":3}
>>> k = reversed(d)
>>> print(next(k))
three
>>>
(2)setdefault(key[, default])是字典对象的方法。如果字典存在键 key ,返回它的值。如果不存在,插入值为 default 的键 key,并返回 default。default是可选参数。
案例代码:
>>> d = {"one":1,"two":2,"three":3}
>>> d.setdefault("four",4)
4
>>> print(d)
{'one': 1, 'two': 2, 'three': 3, 'four': 4}
(3)update([other])是字典对象的方法,该方法使用来自 other 的键/值对更新字典,覆盖原有的键。
参数other可以是一个字典对象,也可以是一个包含键/值对(以长度为二的元组或其他可迭代对象表示)的可迭代对象。
案例代码:
>>> d = {"one":1,"two":2,"three":3}
>>> d.update([("five",5),("six",6)])
>>> print(d)
{'one': 1, 'two': 2, 'three': 3, 'five': 5, 'six': 6}
>>> d.update([("one",10),("two",20)])
>>> print(d)
{'one': 10, 'two': 20, 'three': 3, 'five': 5, 'six': 6}
>>>
(4)copy()是字典对象的方法,该方法返回字典对象的一个浅拷贝。浅拷贝只拷贝父对象,不会拷贝对象内部的子对象,当对象内部的子对象内容发生改变时,拷贝后的子对象也会发生改变。这是因为对象内的子对象和拷贝后的子对象是同一个内存地址。
案例代码:
>>> a = {1: [1,2,3]}
>>> b = a.copy()
>>> print(a,b)
{1: [1, 2, 3]} {1: [1, 2, 3]}
>>> # 修改a对象key为1的值
>>> a[1].append(4)
>>> print(a,b)
{1: [1, 2, 3, 4]} {1: [1, 2, 3, 4]}
>>>
从代码中可以看出,当修改a对象key为1的值后,b对象key为1的值也发生同样变化。