Python字典底层讲解

简介: Python字典底层讲解

Dictonary字典


字典在python中是以键值对(k-v)的形式进行存储。添加,删除,修改,查询的时间复杂度均是O(1)。


(1)哈希表(Hashtable)


哈希表(也叫散列表),根据关键值对(Key-value)而直接进行访问的数据结构。它通过把key和value映射到表中一个位置来访问记录,这种查询速度非常快,更新也快。而这个映射函数叫做哈希函数,存放值的数组叫做哈希表。 哈希函数的实现方式决定了哈希表的搜索效率。具体操作过程是:


数据添加:把key通过哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里。


数据查询:再次使用哈希函数将key转换为对应的数组下标,并定位到数组的位置获取value。


但是,对key进行hash的时候,不同的key可能hash出来的结果是一样的,尤其是数据量增多的时候,这个问题叫做哈希冲突。如果解决这种冲突情况呢?通常的做法有两种,一种是链接法,另一种是开放寻址法,Python选择后者。


(2)开放寻址法(Open addressing)


开放寻址法中,所有的元素都存放在散列表里,当产生哈希冲突时,通过一个探测函数计算出下一个候选位置,如果下一个获选位置还是有冲突,那么不断通过探测函数往下找,直到找个一个空槽来存放待插入元素。


PYDICTENTRY


字典中的一个key-value 键值对元素称为entry,对用到python内部是PyDictEntry。

typedef struct {
    /* Cached hash code of me_key.  Note that hash codes are C longs.
     * We have to use Py_ssize_t instead because dict_popitem() abuses
     * me_hash to hold a search finger.
     */
    Py_ssize_t me_hash;
    PyObject *me_key;
    PyObject *me_value;
} PyDictEntry;

1.Unused: me_key == me_value == NULL。 Unused是entry的初始状态,key和value都为NULL。插入元素时,Unused状态转换成Active状态。这是me_key为NULL的唯一情况。


2.Active: me_key != NULL and me_key != dummy 且 me_value != NULL。 插入元素后,entry就成了Active状态,这是me_value唯一不为NULL的情况,删除元素时Active状态刻转换成Dummy状态。


3.Dummy: me_key == dummy 且 me_value == NULL。此处的dummy对象实际上一个PyStringObject对象,仅作为指示标志。Dummy状态的元素可以在插入元素的时候将它变成Active状态,但它不可能再变成Unused状态。


为什么entry有Dummy状态呢?这是因为采用开放寻址法中,遇到哈希冲突时会找到下一个合适的位置,例如某元素经过哈希计算应该插入到A处,但是此时A处有元素的,通过探测函数计算得到下一个位置B,仍然有元素,直到找到位置C为止,此时ABC构成了探测链,查找元素时如果hash值相同,那么也是顺着这条探测链不断往后找,当删除探测链中的某个元素时,比如B,如果直接把B从哈希表中移除,即变成Unused状态,那么C就不可能再找到了,因为AC之间出现了断裂的现象,正是如此才出现了第三种状态—Dummy,Dummy是一种类似的伪删除方式,保证探测链的连续性。


python_entry_status

typedef struct _dictobject PyDictObject;
struct _dictobject {
    PyObject_HEAD
    Py_ssize_t ma_fill;  /* # Active + # Dummy */
    Py_ssize_t ma_used;  /* # Active */
    /* The table contains ma_mask + 1 slots, and that's a power of 2.
     * We store the mask instead of the size because the mask is more
     * frequently needed.
     */
    Py_ssize_t ma_mask;
    /* ma_table points to ma_smalltable for small tables, else to
     * additional malloc'ed memory.  ma_table is never NULL!  This rule
     * saves repeated runtime null-tests in the workhorse getitem and
     * setitem calls.
     */
    PyDictEntry *ma_table;
    PyDictEntry *(*ma_lookup)(PyDictObject *mp, PyObject *key, long hash);
    PyDictEntry ma_smalltable[PyDict_MINSIZE];
};

ma_fill :所有处于Active以及Dummy的元素个数


ma_used :所有处于Active状态的元素个数


ma_mask :所有entry的元素个数(Active+Dummy+Unused)


ma_smalltable:创建字典对象时,一定会创建一个大小为PyDict_MINSIZE==8的PyDictEntry数组。


ma_table:当entry数量小于PyDict_MINSIZE,ma_table指向ma_smalltable的首地址,当entry数量大于8时,Python把它当做一个大字典来处理,此刻会申请额外的内存空间,同时将ma_table指向这块空间。


ma_lookup:字典元素的搜索策略


PyDictObject使用PyObject_HEAD而不是PyObject_Var_HEAD,虽然字典也是变长对象,但此处并不是通过ob_size来存储字典中元素的长度,而是通过ma_used字段。

相关文章
|
24天前
|
存储 开发者 Python
Python中的collections模块与UserDict:用户自定义字典详解
【4月更文挑战第2天】在Python中,`collections.UserDict`是用于创建自定义字典行为的基类,它提供了一个可扩展的接口。通过继承`UserDict`,可以轻松添加或修改字典功能,如在`__init__`和`__setitem__`等方法中插入自定义逻辑。使用`UserDict`有助于保持代码可读性和可维护性,而不是直接继承内置的`dict`。例如,可以创建一个`LoggingDict`类,在设置键值对时记录操作。这样,开发者可以根据具体需求定制字典行为,同时保持对字典内部管理的抽象。
|
1月前
|
存储 索引 Python
python字典:怎么取出key对应的值
python字典:怎么取出key对应的值
37 0
|
1月前
|
存储 数据库 索引
Python新手常见问题一:列表、元组、集合、字典区别是什么?
本文针对Python编程新手常遇到的问题,详细阐述了列表(List)、元组(Tuple)、集合(Set)和字典(Dictionary)这四种数据结构的核心区别。列表是一种有序且可变的数据序列,允许元素重复;元组同样有序但不可变,其内容一旦创建就不能修改;集合是无序、不重复的元素集,强调唯一性,主要用于数学意义上的集合操作;而字典则是键值对的映射容器,其中键必须唯一,而值可以任意,它提供了一种通过键查找对应值的有效方式。通过对这些基本概念和特性的对比讲解,旨在帮助初学者更好地理解并运用这些数据类型来解决实际编程问题。
37 1
|
2天前
|
JSON 数据格式 索引
python 又一个点运算符操作的字典库:Munch
python 又一个点运算符操作的字典库:Munch
19 0
|
15天前
|
安全 Python
python字典的内置方法
Python字典主要方法包括:`keys()`(返回所有键)、`values()`(返回所有值)、`items()`(返回所有键值对)、`get()`(安全取值,键不存在时返回默认值)、`setdefault()`(设置默认值)、`update()`(合并字典)、`pop()`(删除并返回值)、`clear()`(清空字典)、`copy()`(浅拷贝)、`fromkeys()`(新建字典并设置默认值)、`popitem()`(随机删除键值对)。
8 0
|
23天前
|
存储 Java 程序员
【Python】6. 基础语法(4) -- 列表+元组+字典篇
【Python】6. 基础语法(4) -- 列表+元组+字典篇
41 1
|
23天前
|
存储 Python
python基础篇: 详解 Python 字典类型内置方法
python基础篇: 详解 Python 字典类型内置方法
28 1
|
29天前
|
C语言 Python
Python字典推导式:高效构建字典的利器
在Python编程中,字典推导式(Dictionary Comprehension)是一种强大的构造工具,它允许我们以简洁的方式从现有可迭代对象创建新的字典。通过字典推导式,我们可以轻松地对数据进行转换、过滤或重新组织,以符合特定的需求。本文将深入探讨字典推导式的概念、语法和应用场景,帮助读者更好地掌握这一高效的编程工具。
|
1月前
|
Python
深入解析Python中的字典推导式
深入解析Python中的字典推导式
|
1月前
|
存储 Java Python
助你更好的理解 Python 字典
助你更好的理解 Python 字典