Python的Dict对象源码分析

 更新时间:2023年08月16日 10:19:46   作者:efeics  
这篇文章主要介绍了Python的Dict对象源码分析,PyDictObject即字典对象,类似于C++ STL中的map,但STL中以红黑树实现,Python中dict以hash表(散列表)实现,需要的朋友可以参考下

Python的Dict对象源码分析

PyDictObject即字典对象,类似于C++ STL中的map,但STL中以红黑树实现,Python中dict以hash表(散列表)实现。

散列表,通过Hash函数将特定对象映射为特定数字;

当装载率大于2/3时,散列冲突概率增加,解决散列冲突,STL采用开链法,而Python采用开放定址法。

开放定址法法,在探测冲突链上依次跳转,如果删除探测冲突链上某个元素,会使探测冲突链断裂。

故而,删除某元素时,不可在物理上真正删除。

1、entry与dict对象

typedef struct {
    Py_ssize_t me_hash;	     // key的hash值
    PyObject *me_key;
    PyObject *me_value;
} PyDictEntry;
struct _dictobject {
    PyObject_HEAD
    Py_ssize_t ma_fill;        /* # Active + # Dummy */
    Py_ssize_t ma_used;        /* # Active */
    Py_ssize_t ma_mask;        // dict对象所拥有的entry数量
    PyDictEntry *ma_table;     // 指向存放元素的内存区域
    PyDictEntry *(*ma_lookup)(PyDictObject *mp, PyObject *key, long hash);    // 搜索函数指针
    PyDictEntry ma_smalltable[PyDict_MINSIZE];      // 自带少量元素内存
};

元素数量不同时,可使用不同策略

2、搜索策略

由于采用开放定址法,探测冲突链上元素不可删除,Python将每个元素设为三种状态。

  1. 从未使用是unused
  2. 正在使用是Active
  3. 当将某个Active的元素删除时将其置为dummy。

通过ma_key与ma_value的值来判定状态。

Python每种类型的对象都实现了各自的hash函数,如string对象函数函数如下:

int len = strObject->length;
unsignedchar * p = (unsignedchar *)strObject->value;
long x = *p << 7;
while (--len >= 0)
    x = (1000003*x) ^ *p++;
x ^= strObject->length;
if (x == -1)
    x = -2;
strObject->hashValue = x;

产生散列冲突时,采用二次探测函数,Python中如下:

for (perturb = hash; ; perturb >>= 5) {
	i = (i << 2) + i + perturb + 1;
	ep = &ep0[i & mask];
}

冲突探测链开端为通过hash函数找到的第一个entry,结尾为第一个unused状态entry。

搜索整体思想为,在探测链上依次寻找;

遇到dummy状态则记录为freesplot,并继续探测;

直至探测到匹配的元素,返回该对象;

或者直到最后一个元素即unused状态entry,此时若freesplot为空则返回该unused,若不为空则返回freesplot记录的dummy。

有图示几种情况,1-6依次返回A、C、D、E、X、Y。

3、dict对象使用

dict对象的各种应用均依赖与搜索策略,而在python中使用PyStringObject*做key的情况特别多,python默认使用针对string优化的搜索函数,如果key不是string对象,返回通用搜索函数。

元素的插入,需注意dict对象会自动调整内存大小,以装载率大于2/3为基准。

调整大小时会重新分布元素,故dummy态不再需要,被销毁。 元素的删除,需注意该元素置为dummuy态。

元素的设置,若存在该key,直接更改value;

若不存在,添加该entry,即(key,value)。

4、dict对象缓冲池

和list对象缓冲池类似,在此就不多赘述。

到此这篇关于Python的Dict对象源码分析的文章就介绍到这了,更多相关Python的Dict源码内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 这三个好用的python函数你不能不知道!

    这三个好用的python函数你不能不知道!

    作为21世纪最流行的语言之一,Python当然有很多有趣的功能值得深入探索和研究.今天通过理论和实际例子来讨论,需要的朋友可以参考下
    2021-06-06
  • Python之字典添加元素的几种方法

    Python之字典添加元素的几种方法

    这篇文章主要介绍了Python之字典添加元素的几种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • Python发送邮件实现基础解析

    Python发送邮件实现基础解析

    这篇文章主要介绍了Python发送邮件实现基础解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • python opencv实现gif图片分解的示例代码

    python opencv实现gif图片分解的示例代码

    这篇文章主要介绍了python opencv实现gif图片分解的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • anaconda安装后打不开解决方式(亲测有效)

    anaconda安装后打不开解决方式(亲测有效)

    Anaconda是一个和Canopy类似的科学计算环境,但用起来更加方便,下面这篇文章主要给大家介绍了关于anaconda安装后打不开解决的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2022-09-09
  • 详解Python程序与服务器连接的WSGI接口

    详解Python程序与服务器连接的WSGI接口

    这篇文章主要介绍了Python程序与服务器连接的WSGI接口,是Python网络编程学习当中的重要内容,需要的朋友可以参考下
    2015-04-04
  • selenium+PhantomJS爬取豆瓣读书

    selenium+PhantomJS爬取豆瓣读书

    这篇文章主要为大家详细介绍了selenium+PhantomJS爬取豆瓣读书,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-08-08
  • Python面向对象之入门类和对象

    Python面向对象之入门类和对象

    这篇文章主要为大家介绍了Python入门类和对象,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-12-12
  • pandas 时间偏移的实现

    pandas 时间偏移的实现

    时间偏移就是在指定时间往前推或者往后推一段时间,即加减一段时间之后的时间,本文使用Python实现,感兴趣的可以了解一下
    2021-08-08
  • python矩阵转换为一维数组的实例

    python矩阵转换为一维数组的实例

    今天小编就为大家分享一篇python矩阵转换为一维数组的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-06-06

最新评论