阅读 104

Python字典内存浅析

这是我参与更文挑战的第 8 天,活动详情查看: 更文挑战

1. 字典简介

1.1 什么是字典?

字典是python数据类型之一。

字典通过花括号来包含数据项。

字典样式:info = {'name':'JUEJING','address':'juejin.cn'}

  • 字典的每个元素由2部分组成,键:值
  • 字典是根据键来找对应的值

image.png

1.2 字典特点
  • 字典与列表、集合一样,都是属于可变数据类型
  • 字典和列表一样,也能够存储多个数据

字典是由可key:value键值对组成的,

  • 键对象具有唯一性,因此只有不可变数据类型(数字,字符串和元组)才能作为键键对象
  • 值对象可以为python的任意数据类型

image.png

# 定义一个字典

DICT = {"num":8,"List":["List",8],"Tuple":("Tuple",5),"Dict":{"Name":"Dictonary"},"STR":"STR",("world",10):"Earth",5:"Lucky"}

# 打印字典

print(DICT)
复制代码

image.png

image.png

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中,是怎么进行的呢?

  1. 首先第一步要计算student[“name”]的散列值。
>>> bin(hash("name"))
'0b10XXX1100011100111101001001111101010100010101000'
复制代码
  1. 得到hash值后,我们从hash值最右边3位数字作为偏离量,即“000”,十进制数字是0。
  2. 我们查看对应的bucket是否为空,如果为空,则将键值对放进去。
  3. 如果不为空,则依次去右边3位作为偏离量,即“101”,十进制数字是5.
  4. 再看偏离量为4的bucket是否为空,直到找到为空的bucket将键值对放进去。

字典

2.2 字典查找值过程
# 定义一个字典
student = {"name":"Tom","age":7,"sex":"boy"}

# 根据键对象进行取值

print(student["name"])

复制代码

去取student的名字,这个过程是怎么运作的?

  1. 我们要计算student["name"] 里面的"name"对象
>>> bin(hash("name"))
'0b10XXX1100011100111101001001111101010100010101000'
复制代码
  1. 确定偏离量。散列值的最右边3位数字作为偏离量 "000",十进制数字是0。
  2. 查看偏离量0,对应的bucket是否为空,如果未空,则返回None。
  3. 如果不为空,则将这个bucket的键对象计算出对应的散列值
  4. 和student["name"]的"name"散列值进行比较
  5. 如果两个散列值相等,则将对应数组里的值对象返回
  6. 如果不相等,则再依次取其他几位数字,重新计算偏离量。
  7. 依次取完,仍然没有找到,则返回None。

字典

总结

字典用法总结:

  1. 键必须可散列 (1)数字、字符串、元组,都是可散列的。 (2)自定义对象需要支持下面三点: 支持hash()函数 支持通过__eq__()方法检测相等性 若a == b为真,则hash(a)==hash(b)也为真
  2. 字典在内存中开销巨头,典型的空间换时间
  3. 键查询速度很快
  4. 往字典里面添加新键可能导致扩容,导致散列表中键的次序变化,因此不要在遍厉字典的同时进行字典的修改。
文章分类
后端
文章标签