关于Python中字典dict的存储原理详解

 更新时间:2023年05月19日 11:47:45   作者:遇见糖糖  
Python字典是另一种可变容器模型,可存储任意类型对象。如字符串、数字、元组等其他容器模型,因为字典是无序的所以不支持索引和切片,需要的朋友可以参考下

字典的定义

字典是"键值对"的无序可变序列,字典中的每个元素都是一个"键值对",包含:"键对象",和"值对象".可以通过"键对象"实现快速获取,删除,更新对应的"值对象".

列表中我们通过"下标数字"找到对应的对象,字典中通过"键对象"找到对应的"值对象"."键"是任意的不可变数据,比如:整数,浮点数,字符串,元组.但是:列表,字典,集合这些可变的对象,不能作为"键".并且"键"不可重复."值"可以是任意的数据,并且可重复.

一个典型的字典的定义方式:

取字典的值

字典的创建:

1.可以使用{},dict()来创建字典对象

a = {}
b = dict(key1=value1,key2=value2)

注:这里面的key不需要带"引起"直接就可以使用

c = dict([key1,key2],[value1,value2])

2.通过zip()创建字典对象

k = ["name","age","job"]
b = ["tangmoumou","18","student"]
d = dict(zip(k,b))

3.通过fromkeys创建键值为空的字典

a = dict.fromkeys('name','age','job'])

字典元素的访问

为了测试各种访稳方法,先预设一个字典对象:

a = {"name":"唐","age":18,"job":"programmer"}
  • 通过键获取值,若键不存在,则抛出异常
  • 通过get()方法获得 "值",推荐使用

有的时候:返回具体的值,当指定键不存在时,返回None;也可以设置指定键不存在的时候默认返回的对象.推荐使用get()获取值对象

设置get的默认返回值

  • 列出所有额键值对
a.items()

  • 列出所有键,列出所有的值
a.keys()
a.values()

  • len()键值对的个数
  • 检测一个 "键"是否在字典中

字典元素添加,修改和删除

1.给字典新增 键值对,如果键已经存在,则覆盖 旧的建制地;如果 键不存在,则新增 键值对

2.使用update()将字典中所有键值对全部添加到旧字典对象上.如果key有重复,则直接覆盖

3.字典中元素的删除,可以使用del()方法,或者clear()删除所有的键值对;pop()删除指定的键值对,并返回对应的"值对象"

4.popitem():随机删除和返回该键值对.字典是"无序可变序列",因此没有第一个元素,最后一个元素的概念:popitem弹出随机的项,因此字典并没有"最后的元素"或者其他有关熟悉怒的概念,若想一个接一个移除并处理项,这个方法就非常有效(因为不用首先获取键的列表)

序列解包

序列解包可用于元组,列表,字典.序列解包可以让我们方便的对多个变量赋值.

序列解包用于字典时,默认是对"键"进行操作;如果需要对键值对操作,则需要使用items();如果需要对"值"进行操作,则需要使用values();

s = {"name":"唐某某","age":18,"job":"student"}

字典核心底层原理(重要)

字典对象的核心是散列表.散列表是一个稀疏数组(总是有空白元素的数组),数组的每个单元叫做bucket,每个bucket有两部分:一个是键对象的引用,一个是值对象的引用.

由于,所有bucket结构和大小一致,我么可以通过偏移量来指定bucket.

将一个键值对放进字典的底层过程

a={}
a["name"] = "tang"

当将"name"="tang"这个键值对放到字典对象a中,首先第一步要计算键"name"的散列表.Python可以使用hash()来计算.

由于数组长度为8,我们可以拿计算出的散列值,最右边3位数作为偏移量,即"010",十进制是数字2,我们查看偏移量2,对应的bucket是否为空,如果为空,则将键值放进去,如果不为空,依次取右边3位作为偏移量'101',十进制是数字5,再查看偏移量5的bucket是否为空.直到栈为空的bucket将键值放进去

根据键查找"键值对"的底层过程

一个键值对是如果存储到数组中的,根据键值对象取到值对象,理解起来就简单了

a.get("name")

当我们调用a.get("name"),就是根据键"name"查找"键值对",从而找到值"tang"

第一步,我们仍要计算"name"对象的散列值:

bin(hash("name"))

和存储的底层流程算法一致,也是一次取散列值不同的数字,假设数组长度为8,我们可以拿计算出的散列值的最右边3位数字作为偏移量,即"010",十进制是数字2,我们查看偏移量5,对应的bucket是否为空.如果为空则返回None.如果不为空,则将这个bucket对象的键对象计算对应的散列值,和我们的散列值进行比较,如果相等,则将对应"值对象"返回,如果不相等,则一次取其它几位数字,重新计算偏移量,依次取完后仍没有找到哦啊,则返回None.

用法总结:

  • 1.键必须可散列
    • 数字,字符串,元组,都是可散列的
    • 自定义对象需要支持下面三点;
    • 支持hash()函数
    • 支持通过__eq__()方法尖刺相等性
    • 做a==b为真,则hash(a)==hash(b)也为真.
  • 2.字典在内存中开销巨大,典型的空间换时间.
  • 3.键值查询速度很快
  • 4.往字典烈面添加新键可能导致扩容,导致散列表中的键的次序发生变化.因此,不要在遍历字典的同时对字典的修改.

到此这篇关于关于Python中字典dict的存储原理详解的文章就介绍到这了,更多相关Python字典存储原理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

最新评论