这是我参与更文挑战的第 8 天,活动详情查看: 更文挑战
1. 字典简介
1.1 什么是字典?
字典是python数据类型之一。
字典通过花括号来包含数据项。
字典样式:info = {'name':'JUEJING','address':'juejin.cn'}
- 字典的每个元素由2部分组成,键:值
- 字典是根据键来找对应的值
1.2 字典特点
- 字典与列表、集合一样,都是属于可变数据类型
- 字典和列表一样,也能够存储多个数据
字典是由可key:value键值对组成的,
- 键对象具有唯一性,因此只有不可变数据类型(数字,字符串和元组)才能作为键键对象
- 值对象可以为python的任意数据类型
# 定义一个字典
DICT = {"num":8,"List":["List",8],"Tuple":("Tuple",5),"Dict":{"Name":"Dictonary"},"STR":"STR",("world",10):"Earth",5:"Lucky"}
# 打印字典
print(DICT)
2. 字典内存分布
字典对象的核心是离散列表。散列表是一个稀疏数组(总是有空白元素的数组)
数组的每个单元叫做bucket。每个bucket有两个部分,一个是键对象的引用,一个是值对象的引用。
由于,所有bucket的结构大小一致,我们可以通过偏离量来读取指定的bucket。
2.1 键值对存储过程
# 我们定义一个student的字典对象
student = {}
# 添加:"name":"Tom","age":7,"sex":"boy"
student["name"] = "Tom"
student["age"] = 7
student["sex"] = "boy"
我们要把 “name” = “Tom” 这个键值对放到字典对象student中,是怎么进行的呢?
- 首先第一步要计算student[“name”]的散列值。
>>> bin(hash("name"))
'0b10XXX1100011100111101001001111101010100010101000'
- 得到hash值后,我们从hash值最右边3位数字作为偏离量,即“000”,十进制数字是0。
- 我们查看对应的bucket是否为空,如果为空,则将键值对放进去。
- 如果不为空,则依次去右边3位作为偏离量,即“101”,十进制数字是5.
- 再看偏离量为4的bucket是否为空,直到找到为空的bucket将键值对放进去。
2.2 字典查找值过程
# 定义一个字典
student = {"name":"Tom","age":7,"sex":"boy"}
# 根据键对象进行取值
print(student["name"])
去取student的名字,这个过程是怎么运作的?
- 我们要计算student["name"] 里面的"name"对象
>>> bin(hash("name"))
'0b10XXX1100011100111101001001111101010100010101000'
- 确定偏离量。散列值的最右边3位数字作为偏离量 "000",十进制数字是0。
- 查看偏离量0,对应的bucket是否为空,如果未空,则返回None。
- 如果不为空,则将这个bucket的键对象计算出对应的散列值
- 和student["name"]的"name"散列值进行比较
- 如果两个散列值相等,则将对应数组里的值对象返回
- 如果不相等,则再依次取其他几位数字,重新计算偏离量。
- 依次取完,仍然没有找到,则返回None。
总结
字典用法总结:
- 键必须可散列 (1)数字、字符串、元组,都是可散列的。 (2)自定义对象需要支持下面三点: 支持hash()函数 支持通过__eq__()方法检测相等性 若a == b为真,则hash(a)==hash(b)也为真
- 字典在内存中开销巨头,典型的空间换时间
- 键查询速度很快
- 往字典里面添加新键可能导致扩容,导致散列表中键的次序变化,因此不要在遍厉字典的同时进行字典的修改。