字典
什么是字典
字典并不是什么全新的概念,早在上小学时,你就已经接触过字典,没错,就是《新华字典》,新华字典的结构和python语言中的字典,在结构上是一样的。
咱们以读音来查找一个汉字,比如”张”这个字,读音是zhang,一声,你一定可以在字典里找到与它对应的页数,假设是第100页,那么zhang 和 100之间就有一个映射关系,你知道了zhang,也就知道了100。
另一个较为常见的例子是手机通讯录,你想找一个人的电话时,你应该在通讯录里找到这个人的名字,然后点进去查看它的电话号,姓名和电话号之间存在着映射关系,你知道姓名,就知道电话号,下面这张图展示了字典的数据结构
左侧是key,右侧是value。
python字典 (dict)
python中的字典(dict)是数据的无序集合, 与列表,元组,集合将单个值作为存储数据不同, 字典存储的是key:value对, 字典中存储的数据总是成对的, key被称之为键, value称之为值, 值可以是任意数据且可重复, 而键不可重复且必须是可hash的。
1. 创建一个字典
1.1 创建字典
字典是一个容器类型数据,字典里存储的是键值对,键值对用冒号分割key与value,每个键值(key-value)对用逗号分割,整个字典包裹在花括号{}中。
下面是一个字典的示例
contacts_dict = {"小王": '13892339876',"小张": '13898320987',"小李": '13890348745'}
如果字典里没有任何键值对,那么它就是一个空字典
empty_dict = {}
如果想知道字典中有多少数据,可以使用len函数来获取
print(len(contacts_dict))
想要知道一个key是否在字典中存在,使用in 或者not in 成员操作符
print('小王' in contacts_dict)
1.2 什么数据可以做key,什么数据可以做value
什么数据可以做key
并不是所有的数据都可以做key,想成为key,是有要求的,数据必须是可hash的,下面罗列的5种数据类型是可以做字典key的数据类型
- bool
- int
- float
- 字符串
- 元组
下面3中数据类型不可以做字典的key
- 列表
- 集合
- 字典
凡是可变对象都不可以做字典的key,凡是不可变对象,都可以做字典的key。
bool类型的数据只有True和False两个值,虽然他们可以做字典的key,但实践时,你最好不要这样做,会导致古怪的问题,比如下面的代码
int_dict = {1: '1做key',True: 'True做key'}print(int_dict)
执行代码,输出结果为
{1: 'True做key'}
是不是很奇怪,明明两个键值对,实际输出却只有一个,而且key从True变成了1,这是怎么一回事?
print(1==True) # 判断1是否与True相等print(issubclass(bool, int)) # 判断bool类型是否为int类型的子类
程序输出结果为
TrueTrue
1 和 True是相等的,0和False是相等的,bool类型是int类型的子类,这就是原因,在定义字典时,第二个键值对覆盖了前面的键值对,在字典中,key是不会出现重复的,后加入的总是会覆盖前面的。
什么数据可以做value
对于value,字典没有任何要求,任何数据都可以做value,包括列表,集合,甚至是字典。
dic = {'list': [2, 3, 4],'set': set([2, 4, 6]),'dict': {'小明': 99}}
2. 新增键值对和修改value
下面的字典里存储了学生的语文考试分数
score_dict = {'小明': 96,'小刚': 98,'小红': 94}
现在你发现,小丽的分数还没有写入到字典中,她考了100分,你需要新增一个键值对,记录小丽的分数
score_dict['小丽'] = 100
这就是字典里新增键值对的方式,一对中括号紧跟在字典后面,中括号里写key,等号右侧写value,是不是很简单。
如果一个key原本已经存在了,那么上面这种操作方式会产生什么样的结果呢?
score_dict['小明'] = 99
‘小明’这个key已经存在于字典中了,上面这种写法尝试新增,但不会发生新增这种事情,因为字典里的key不允许重复,因此,最终的结果是value被修改,字典被修改成
score_dict = {'小明': 99,'小刚': 98,'小红': 94}
简单总结一下,对于score_dict[‘小明’] = 99 这种代码,如果key不存在,那么就会新增键值对,如果key已经存在,就会修改value
3. 访问字典里的值
想要访问字典里的值,必须提供key,对字典的任何操作,都必须通过key才能进行,就如同对列表的操作都必须通过索引才能进行一样。
比如你想知道小红的语文分数,那你应该这样写代码
score_dict = {'小明': 99,'小刚': 98,'小红': 94}print(score_dict['小红'])
score_dict[‘小红’] 这种写法的意思就是获取’小红’这个key所对应的value,如果你提供了一个并不存在的key,则会引发一个KeyError错误
print(score_dict['小丽'])
错误为
Traceback (most recent call last):File "/Users/kwsy/PycharmProjects/pythonclass/mytest/demo.py", line 7, in <module>print(score_dict['小丽'])KeyError: '小丽'
4. 删除字典里的键值对
现在想要从字典里删除小红的成绩,和访问字典里的key一样,你必须指定要删除的key
del score_dict['小红']
除了这种方法外,你还可以使用字典的pop方法
score_dict.pop('小红')
python嵌套字典
同嵌套列表一样,python的字典作为一个容器,可以在字典里存储字典,类似下面的形式
stu_dict = {'name': '小明','age': 12,'score': {'语文': 90,'数学': 98}}
在嵌套列表,嵌套字典中,对于嵌套的层次,没有任何要求,只要你自己能理清嵌套逻辑,你想嵌套多少层都可以。
如果你想获取小明的语文分数,那么就需要逐层的来获取value
print(stu_dict['score']['语文'])
stu_dict[‘score’]的值是
{'语文': 90,'数学': 98}
仍然是一个字典,想要获取语文分数,就继续使用[]操作符来获取key所对应的value
python字典方法介绍
| 方法 | 功能作用 |
|---|---|
| clear() | 删除字典内所有的元素 |
| copy() | 返回字典的浅复制 |
| fromkeys() | 以指定key创建一个新的字典 |
| get() | 返回指定key的值 |
| items() | 成对返回所有key和value |
| keys() | 返回字典所有的key |
| values | 返回字典所有value |
| setdefault() | 为key设置对应的默认值 |
| update() | 更新字典 |
| pop() | 删除键值对 |
字典内置的方法可以帮我们实现很多功能,下面逐个介绍他们,讲解他们的用途
1. clear, 删除字典内所有的元素
dic = {'小明': 98}dic.clear()print(dic)
使用clear方法后,字典dic变成了空字典,有人可能会问,这种清空字典的方法和直接将空字典赋值给变量dic有什么区别
dic = {'小明': 98}dic = {}print(dic)
程序最终输出的结果同样是{},dic 变成了空字典。两种方式,变量dic都变成了空字典,但意义不同,使用clear方法,字典在内存中的地址没有发生变化,但是第二种方法,变量dic指向了一个新的空字典,原来的字典被垃圾回收机制回收了,我们可以通过输出变量的内存地址来验证
dic1 = {'小明': 98}print("使用clear方法前,dic1内存地址为", id(dic1))dic1.clear()print(dic1)print("使用clear方法后,dic1内存地址为", id(dic1))print("\n\n分割线"+"*"*30 + "\n"*2)dic2 = {'小明': 98}print("赋值空字典之前,dic1内存地址为", id(dic2))dic2 = {}print(dic2)print("赋值空字典之后,dic1内存地址为", id(dic2))
程序输出结果为
使用clear方法前,dic1内存地址为 4352796640{}使用clear方法后,dic1内存地址为 4352796640分割线******************************赋值空字典之前,dic1内存地址为 4729716312{}赋值空字典之后,dic1内存地址为 4729716168
clear是清空字典,而将一个空字典赋值给变量,并不是清空,只是修改了变量的引用而已。
2. copy, 返回字典的浅复制
dic1 = {'小明': 98}dic2 = dic1.copy()print(dic1)print(dic2)
程序输出结果为
{'小明': 98}{'小明': 98}
dic2是dic1的复制品,他们的内容一模一样,在python中,还有一个模块,可是实现数据的复制功能,它就是copy模块
import copydic1 = {'小明': 98}dic2 = copy.copy(dic1)print(dic1)print(dic2)
这两段代码都实现了浅复制,浅复制是一种危险的复制,建议你不要使用,因为这种复制并没有创建新的对象,因此,你对dic2的修改会影响到dic1
dic1 = {'stu': ['小明', '小红']}dic2 = dic1.copy()dic2['stu'].append('小刚')print(dic1)
程序输出结果为
{'stu': ['小明', '小红', '小刚']}
3. fromkeys,以指定key创建一个新的字典
stu_dict = dict.fromkeys(['小明', '小刚'], 90)print(stu_dict)
程序输出结果为
{'小明': 90, '小刚': 90}
fromkeys方法接受两个参数,第一个参数是序列,可以是列表,也可以是元组,方法将以这个序列里的元素做key,生成新的字典。value由第二个参数来决定,我在代码里传入参数90,所有key所对应的value就都是90,如果不传这个参数,默认value为None
4. get,返回指定key的值
get方法,是一种安全的获取value的方法,如果key不存在,则返回default,default可以由你来指定,如果你不指定,则默认为None
empty_dict = {}print(empty_dict.get('python'))print(empty_dict.get('python', 100))
程序输出结果
None100
5. items(),成对返回所有key和value
items()方法通常被用在字典遍历的场景下
score_dict = {'小明': 96,'小刚': 98,'小红': 94}for key, value in score_dict.items():print(key, value)
items()方法返回一个可迭代对象,使用for循环遍历这个可迭代对象时,得到的是一个元组,元组内包含key和 value
下面的代码向你揭示items()方法返回的对象的本质面目
from collections import Iterablescore_dict = {'小明': 96,'小刚': 98,'小红': 94}iter_obj = score_dict.items()print(isinstance(iter_obj, Iterable))for item in iter_obj:print(item)
程序输出结果为
True('小明', 96)('小刚', 98)('小红', 94)
6. keys,返回字典所有的key
score_dict = {'小明': 96,'小刚': 98,'小红': 94}keys = score_dict.keys()print(keys, type(keys))for key in keys:print(key)
程序输出结果
dict_keys(['小明', '小刚', '小红']) <class 'dict_keys'>小明小刚小红
keys()方法在py2.7里,返回的是包含了所有key的列表,但在py3.6中,返回的是可迭代对象,遍历这个对象,就可以得到字典所有的key
7. values,返回字典所有value
score_dict = {'小明': 96,'小刚': 98,'小红': 94}values = score_dict.values()print(values, type(values))for value in values:print(value)
values()方法返回的是一个可迭代对象,遍历这个可迭代对象,可以获得字典所有的value
8. setdefault,为key设置对应的默认值
这个方法和get有些类似,如果key不存在,则增加新的键值对,如果key已经存在,则不做任何操作
score_dict = {'小明': 96,'小刚': 98,'小红': 94}score_dict.setdefault('小明', 100) # 小明这个key已经存在,因此这行语句不产生任何影响score_dict.setdefault('小丽', 97) # 小丽这个key不存在,增加新的键值对,key为小丽,value为97print(score_dict)
程序输出结果
{'小明': 96, '小刚': 98, '小红': 94, '小丽': 97}
9. update 更新字典
一般的使用模式是dic1.update(dic2),将dic2的内容更新到dic1中
score_dict = {'小明': 96,'小刚': 98,'小红': 94}score_dict2 = {'小明': 100,'小丽': 98,}score_dict.update(score_dict2)print(score_dict)
如果一个key,在两个字典中都存在,则value的最终结果取决于dic2
10. pop 删除键值对
不论是使用del 还是使用pop方法删除字典里的键值对,如果key不存在都会引发KeyError异常,pop与del的不同之处在于,pop会返回所删除键值对的value
score_dict = {'小明': 96,'小刚': 98,'小红': 94}del score_dict['小红']print(score_dict.pop('小明'))print(score_dict)
程序输出结果
96{'小刚': 98}
