# 字典 字典 `dictionary` ,在一些编程语言中也称为 `hash` , `map` ,是一种由键值对组成的数据结构。 顾名思义,我们把键想象成字典中的单词,值想象成词对应的定义,那么—— 一个词可以对应一个或者多个定义,但是这些定义只能通过这个词来进行查询。 ## 基本操作 ### 空字典 **Python** 使用 `{}` 或者 `dict()` 来创建一个空的字典: In [1]: ```py a = {} type(a) ``` Out[1]: ```py dict ``` In [2]: ```py a = dict() type(a) ``` Out[2]: ```py dict ``` 有了dict之后,可以用索引键值的方法向其中添加元素,也可以通过索引来查看元素的值: ### 插入键值 In [3]: ```py a["one"] = "this is number 1" a["two"] = "this is number 2" a ``` Out[3]: ```py {'one': 'this is number 1', 'two': 'this is number 2'} ``` ### 查看键值 In [4]: ```py a['one'] ``` Out[4]: ```py 'this is number 1' ``` ### 更新键值 In [5]: ```py a["one"] = "this is number 1, too" a ``` Out[5]: ```py {'one': 'this is number 1, too', 'two': 'this is number 2'} ``` ### 初始化字典 可以看到,Python使用`key: value`这样的结构来表示字典中的元素结构,事实上,可以直接使用这样的结构来初始化一个字典: In [6]: ```py b = {'one': 'this is number 1', 'two': 'this is number 2'} b['one'] ``` Out[6]: ```py 'this is number 1' ``` ### 字典没有顺序 当我们 `print` 一个字典时,**Python**并不一定按照插入键值的先后顺序进行显示,因为字典中的键本身不一定是有序的。 In [7]: ```py print a ``` ```py {'two': 'this is number 2', 'one': 'this is number 1, too'} ``` In [8]: ```py print b ``` ```py {'two': 'this is number 2', 'one': 'this is number 1'} ``` 因此,**Python**中不能用支持用数字索引按顺序查看字典中的值,而且数字本身也有可能成为键值,这样会引起混淆: In [9]: ```py # 会报错 a[0] ``` ```py --------------------------------------------------------------------------- KeyError Traceback (most recent call last) in () 1 # 会报错 ----> 2 a[0] KeyError: 0 ``` ### 键必须是不可变的类型 出于hash的目的,Python中要求这些键值对的**键**必须是**不可变**的,而值可以是任意的Python对象。 一个表示近义词的字典: In [10]: ```py synonyms = {} synonyms['mutable'] = ['changeable', 'variable', 'varying', 'fluctuating', 'shifting', 'inconsistent', 'unpredictable', 'inconstant', 'fickle', 'uneven', 'unstable', 'protean'] synonyms['immutable'] = ['fixed', 'set', 'rigid', 'inflexible', 'permanent', 'established', 'carved in stone'] synonyms ``` Out[10]: ```py {'immutable': ['fixed', 'set', 'rigid', 'inflexible', 'permanent', 'established', 'carved in stone'], 'mutable': ['changeable', 'variable', 'varying', 'fluctuating', 'shifting', 'inconsistent', 'unpredictable', 'inconstant', 'fickle', 'uneven', 'unstable', 'protean']} ``` 另一个例子: In [11]: ```py # 定义四个字典 e1 = {'mag': 0.05, 'width': 20} e2 = {'mag': 0.04, 'width': 25} e3 = {'mag': 0.05, 'width': 80} e4 = {'mag': 0.03, 'width': 30} # 以字典作为值传入新的字典 events = {500: e1, 760: e2, 3001: e3, 4180: e4} events ``` Out[11]: ```py {500: {'mag': 0.05, 'width': 20}, 760: {'mag': 0.04, 'width': 25}, 3001: {'mag': 0.05, 'width': 80}, 4180: {'mag': 0.03, 'width': 30}} ``` 键(或者值)的数据类型可以不同: In [13]: ```py people = [ {'first': 'Sam', 'last': 'Malone', 'name': 35}, {'first': 'Woody', 'last': 'Boyd', 'name': 21}, {'first': 'Norm', 'last': 'Peterson', 'name': 34}, {'first': 'Diane', 'last': 'Chambers', 'name': 33} ] people ``` Out[13]: ```py [{'first': 'Sam', 'last': 'Malone', 'name': 35}, {'first': 'Woody', 'last': 'Boyd', 'name': 21}, {'first': 'Norm', 'last': 'Peterson', 'name': 34}, {'first': 'Diane', 'last': 'Chambers', 'name': 33}] ``` ### 使用 dict 初始化字典 除了通常的定义方式,还可以通过 `dict()` 转化来生成字典: In [14]: ```py inventory = dict( [('foozelator', 123), ('frombicator', 18), ('spatzleblock', 34), ('snitzelhogen', 23) ]) inventory ``` Out[14]: ```py {'foozelator': 123, 'frombicator': 18, 'snitzelhogen': 23, 'spatzleblock': 34} ``` 利用索引直接更新键值对: In [15]: ```py inventory['frombicator'] += 1 inventory ``` Out[15]: ```py {'foozelator': 123, 'frombicator': 19, 'snitzelhogen': 23, 'spatzleblock': 34} ``` ## 适合做键的类型 在不可变类型中,整数和字符串是字典中最常用的类型;而浮点数通常不推荐用来做键,原因如下: In [16]: ```py data = {} data[1.1 + 2.2] = 6.6 # 会报错 data[3.3] ``` ```py --------------------------------------------------------------------------- KeyError Traceback (most recent call last) in () 2 data[1.1 + 2.2] = 6.6 3 # 会报错 ----> 4 data[3.3] KeyError: 3.3 ``` 事实上,观察`data`的值就会发现,这个错误是由浮点数的精度问题所引起的: In [17]: ```py data ``` Out[17]: ```py {3.3000000000000003: 6.6} ``` 有时候,也可以使用元组作为键值,例如,可以用元组做键来表示从第一个城市飞往第二个城市航班数的多少: In [19]: ```py connections = {} connections[('New York', 'Seattle')] = 100 connections[('Austin', 'New York')] = 200 connections[('New York', 'Austin')] = 400 ``` 元组是有序的,因此 `('New York', 'Austin')` 和 `('Austin', 'New York')` 是两个不同的键: In [20]: ```py print connections[('Austin', 'New York')] print connections[('New York', 'Austin')] ``` ```py 200 400 ``` ## 字典方法 ### `get` 方法 之前已经见过,用索引可以找到一个键对应的值,但是当字典中没有这个键的时候,Python会报错,这时候可以使用字典的 `get` 方法来处理这种情况,其用法如下: ```py `d.get(key, default = None)` ``` 返回字典中键 `key` 对应的值,如果没有这个键,返回 `default` 指定的值(默认是 `None` )。 In [21]: ```py a = {} a["one"] = "this is number 1" a["two"] = "this is number 2" ``` 索引不存在的键值会报错: In [22]: ```py a["three"] ``` ```py --------------------------------------------------------------------------- KeyError Traceback (most recent call last) in () ----> 1 a["three"] KeyError: 'three' ``` 改用get方法: In [24]: ```py print a.get("three") ``` ```py None ``` 指定默认值参数: In [25]: ```py a.get("three", "undefined") ``` Out[25]: ```py 'undefined' ``` ### `pop` 方法删除元素 `pop` 方法可以用来弹出字典中某个键对应的值,同时也可以指定默认参数: ```py `d.pop(key, default = None)` ``` 删除并返回字典中键 `key` 对应的值,如果没有这个键,返回 `default` 指定的值(默认是 `None` )。 In [26]: ```py a ``` Out[26]: ```py {'one': 'this is number 1', 'two': 'this is number 2'} ``` 弹出并返回值: In [27]: ```py a.pop("two") ``` Out[27]: ```py 'this is number 2' ``` In [28]: ```py a ``` Out[28]: ```py {'one': 'this is number 1'} ``` 弹出不存在的键值: In [29]: ```py a.pop("two", 'not exist') ``` Out[29]: ```py 'not exist' ``` 与列表一样,`del` 函数可以用来删除字典中特定的键值对,例如: In [30]: ```py del a["one"] a ``` Out[30]: ```py {} ``` ### `update`方法更新字典 之前已经知道,可以通过索引来插入、修改单个键值对,但是如果想对多个键值对进行操作,这种方法就显得比较麻烦,好在有 `update` 方法: ```py `d.update(newd)` ``` 将字典`newd`中的内容更新到`d`中去。 In [31]: ```py person = {} person['first'] = "Jmes" person['last'] = "Maxwell" person['born'] = 1831 print person ``` ```py {'born': 1831, 'last': 'Maxwell', 'first': 'Jmes'} ``` 把'first'改成'James',同时插入'middle'的值'Clerk': In [32]: ```py person_modifications = {'first': 'James', 'middle': 'Clerk'} person.update(person_modifications) print person ``` ```py {'middle': 'Clerk', 'born': 1831, 'last': 'Maxwell', 'first': 'James'} ``` ### `in`查询字典中是否有该键 In [33]: ```py barn = {'cows': 1, 'dogs': 5, 'cats': 3} ``` `in` 可以用来判断字典中是否有某个特定的键: In [35]: ```py 'chickens' in barn ``` Out[35]: ```py False ``` In [34]: ```py 'cows' in barn ``` Out[34]: ```py True ``` ### `keys` 方法,`values` 方法和`items` 方法 ```py `d.keys()` ``` 返回一个由所有键组成的列表; ```py `d.values()` ``` 返回一个由所有值组成的列表; ```py `d.items()` ``` 返回一个由所有键值对元组组成的列表; In [36]: ```py barn.keys() ``` Out[36]: ```py ['cows', 'cats', 'dogs'] ``` In [37]: ```py barn.values() ``` Out[37]: ```py [1, 3, 5] ``` In [38]: ```py barn.items() ``` Out[38]: ```py [('cows', 1), ('cats', 3), ('dogs', 5)] ```