# 27 字典和键值对

## 大纲

* 什么是字典
* 字典的排序

## 什么是字典

在生活中我们常用的一种信息来源是通讯录，通讯录一般是由若干个联系人组成，每个联系人可能有姓名、电话号码等信息组成。上堂课我们学习了列表，如果是用列表如果来表示通讯录这种信息，我们可以使用一个嵌套列表来做。

```python
contact = [['张三',135001],['李四',135002],['王五',135003]]
print(contact)
```

```
[['张三', 135001], ['李四', 135002], ['王五', 135003]]
```

如果要取出张三对应的电话号码，我们观察到张三是位于第一个位置，也就是序号为0的位置上，可以用\[0]取出张三的名字和号码，再用\[1]取出对应的号码

```python
contact[0][1]
```

```
135001
```

如果这个通讯录很庞大，我们无法肉眼观察，可以通过列表解析的方法，搜索到张三的号码。

```python
[x[1] for x in contact if x[0]=='张三']
```

```
[135001]
```

用列表来保存和查询通讯录，感觉还是比较麻烦，能不能有更方便的方式呢？是有的。我们可以直接利用python内置的另一种数据类型，字典（dict）。字典就几乎是一个通讯录。

```python
contact_dict = {'张三':135001,'李四':135002,'王五':135003}
print(contact_dict)
type(contact_dict)
```

```
{'张三': 135001, '李四': 135002, '王五': 135003}

dict
```

注意python中字典的定义方式，字典需要用一个大括号将所有内容包起来，上面的字典中有三个元素，元素间需要用逗号间隔开，姓名和号码这一对信息构成一个元素，一般将这种有关联的信息叫做键值对，英文称为key-value，key和value之间用冒号间隔开。用字典来搜索张三的号码就非常简单了。

```python
contact_dict['张三']
```

```
135001
```

字典可以做增删改查的四种操作。查询操作上面已经看到了，新增和修改操作都非常简单直接

```python
contact_dict['小明'] = 135004
print(contact_dict)
```

```
{'张三': 135001, '李四': 135002, '王五': 135003, '小明': 135004}
```

```python
contact_dict['小明'] = 135010
print(contact_dict)
```

```
{'张三': 135001, '李四': 135002, '王五': 135003, '小明': 135010}
```

删除元素是和列表类似，都是使用del命令

```python
del contact_dict['张三'] 
print(contact_dict)
```

```
{'李四': 135002, '王五': 135003, '小明': 135010}
```

可以专门取出字典的所有key值或所有value值，将它们转成列表

```python
list(contact_dict.keys())
```

```
['李四', '王五', '小明']
```

```python
list(contact_dict.values())
```

```
[135002, 135003, 135010]
```

也可以将键值对一起取出来转成列表，可以观察到，列表中的元素是一对值。

```python
list(contact_dict.items())
```

```
[('李四', 135002), ('王五', 135003), ('小明', 135010)]
```

字典的元素也支持循环操作

```python
for k, v in contact_dict.items():
    print(k,v)
```

```
李四 135002
王五 135003
小明 135010
```

字典本身可以支持字典解析，就类似于列表解析一样，我们能通过这种方式来产生字典

```python
contact = [['张三',135001],['李四',135002],['王五',135003]]
contact_dict = {k:v for k,v in contact}
print(contact_dict)
```

```
{'张三': 135001, '李四': 135002, '王五': 135003}
```

而且字典的值可以不只是数字、字符串，它还可以是一个字典，如下面这样。

```python
contact_1 = {'电话':135001,'性别':'男','年龄':20}
contact_2 = {'电话':135002,'性别':'男','年龄':22}
contact_3 = {'电话':135003,'性别':'男','年龄':25}
contact_dict = {'张三':contact_1,'李四':contact_2,'王五':contact_3}
print(contact_dict)
```

```
{'张三': {'电话': 135001, '性别': '男', '年龄': 20}, '李四': {'电话': 135002, '性别': '男', '年龄': 22}, '王五': {'电话': 135003, '性别': '男', '年龄': 25}}
```

```python
print(contact_dict['张三'])
```

```
{'电话': 135001, '性别': '男', '年龄': 20}
```

小结：字典（dict）是我们学到的一种新的数据类型，它和列表类似可以存放一系列的数据，不过区别在于它的存放方式是以键值对的形式存放的，它的键可以是常见的字符串、数字，而值可以更为丰富，包括列表和字典。

## 字典的排序

在上一节，我们是使用列表作为数据类型，实现了单词的计算和排序，我们来试试用字典来实现这种数据存放和排序运算。

```python
word_string = '''Last week I went to the theatre.
I had a very good seat. 
The play was very interesting. 
I did not enjoy it.
A young man and a young woman were sitting behind me. 
They were talking loudly. 
I got very angry. 
I could not hear the actors.
I turned round. 
I looked at the man and the woman angrily.
They did not pay any attention. 
In the end, I could not bear it.
I turned round again.
"I can't hear a word!" I said angrily.
It's none of your business," the young man said rudely.
"This is a private conversation!"
'''
```

```python
text_list = word_string.split()
```

```python
text_list = [w.strip('.,"!') for w in text_list]
```

上面代码我们和之前一样建立一个大的字符串变量，再进行了切分操作和一个列表解析，将得到的单词列表存在text\_list中。然后建立一个空的字典，利用循环遍历单词列表，如果单词不在字典的键中，则新增这个键值对，如果在字典中同将值增加1。

```python
word_freq_dict = {}
for word in text_list:
    if word not in word_freq_dict: #如果单词不在字典的键中
        word_freq_dict[word]=1 #新增这个键值对
    else:
        word_freq_dict[word]=word_freq_dict[word]+1 #将值增加1
```

```python
print(word_freq_dict)
```

```
{'Last': 1, 'week': 1, 'I': 11, 'went': 1, 'to': 1, 'the': 6, 'theatre': 1, 'had': 1, 'a': 4, 'very': 3, 'good': 1, 'seat': 1, 'The': 1, 'play': 1, 'was': 1, 'interesting': 1, 'did': 2, 'not': 4, 'enjoy': 1, 'it': 2, 'A': 1, 'young': 3, 'man': 3, 'and': 2, 'woman': 2, 'were': 2, 'sitting': 1, 'behind': 1, 'me': 1, 'They': 2, 'talking': 1, 'loudly': 1, 'got': 1, 'angry': 1, 'could': 2, 'hear': 2, 'actors': 1, 'turned': 2, 'round': 2, 'looked': 1, 'at': 1, 'angrily': 2, 'pay': 1, 'any': 1, 'attention': 1, 'In': 1, 'end': 1, 'bear': 1, 'again': 1, "can't": 1, 'word': 1, 'said': 2, "It's": 1, 'none': 1, 'of': 1, 'your': 1, 'business': 1, 'rudely': 1, 'This': 1, 'is': 1, 'private': 1, 'conversation': 1}
```

然后我们将这个单词词频字典打印出来，从代码量上可以看到，用字典比用列表更为清晰简单，容易理解。

```python
sorted(word_freq_dict.items(),key=lambda x:x[1],reverse=True)[:10]
```

```
[('I', 11),
 ('the', 6),
 ('a', 4),
 ('not', 4),
 ('very', 3),
 ('young', 3),
 ('man', 3),
 ('did', 2),
 ('it', 2),
 ('and', 2)]
```

最后我们用内置的sorted函数，对生成的字典进行排序，这里我们放入的排序对象是word\_freq\_dict的键值对，和上堂课对课程分数的排序类似
