Python对象 —— Dict对象

Python中的Dict对象

散列表概述

Python中散列表采用了开放引址法,即在发生引址冲突后再次使用散列函数寻址,直到找到空的内存地址

在删除数据时,为了防止寻址链中断,采用了软删除的方法

PyDictObject

关联容器entry

PyDictObject中存储的数据为PyObject *

DictObject存储me_hash:缓冲池,防止出现重复时key在次进行hash

存储value的容器有三个状态:
- Unused:初始态,key与value都是NULL
- Active:激活态,key与value分别存储了数据
- Dummy:删除态,当数据删除时进入Dummy软删除状态

关联容器的实现

PyDictObject是一堆关联容器的集合

PyDictObject的属性:

  • ma_fill:内存的全部元素
  • ma_used:激活态元素的数量
  • ma_smalltable:初始的内存空间,大小为8
  • ma_mask:记录PyDictObject中entry的数量
  • ma_table:指向存储空间的地址的初始位置,当dict申请空存储空间时,ma_table会切换地址

PyDictObject的创建与维护

PyDictObject对象创建

PyDictObject中使用缓冲池

PyDictObject实例的创建过程:

  1. ma_smalltable清空同步设置ma_table和ma_mask
  2. 将ma_table指向ma_smalltable并将ma_mask设置为7

PyDictObject中的元素所有

PyDictObject中有两种搜索策略,一种是lookdict,另一种是lookdict_string。其中lookdict_string是lookdict的特殊形式

lookdict的搜索策略:

  1. hash key找到散列冲突链表
  2. 采用探测函数获取链表中下一个entry
  3. 检查
    • value相同,返回结果
    • entry为unsed态,判断freeslot是否为空
      • 是,返回unsed的entry
      • 否,返回freeslot

插入与删除

插入元素过程存储在PyDict_SetItem方法中:

  1. hash搜索定位
  2. insertdict方法:搜索key,存在替换me_value,不存在则插入
  3. 判断内存是否需要扩大
  4. dictresize扩大内存空间

判断内存空间充足的条件

  1. 装载率小于等于内存空间的2/3
  2. 插入方法是否使用了unused或Dummy状态的entry

内存空间不足时,会扩大为Active entry存储空间的4倍

删除元素的流程:

  1. 搜索entry
  2. 修改entry状态
  3. 修改内存空间,调整PyDictObject对象中维护table使用情况

操作示例

  1. 新建dict
  2. 删除元素(14,14)插入元素(104, 104)
  3. 再次插入(14,14)

PyDictObject对象缓冲池

PyDictObject缓冲池的原理与PyListObject相同,都是存储被删除对象的存储空间,在后面创建对象时使用

posted on 2023-07-15 02:48  lwxc  阅读(124)  评论(0)    收藏  举报