我知道在python中,字典是通过散列键和在数组中存储指针(指向键值对)来实现的,而索引是由散列决定的。
但是键值对本身是如何存储的呢?它们是一起存储的吗(即,在内存中的相邻点中)?它们是以元组还是指针数组的形式存储的,一个指向键,一个指向值?或者完全是别的什么?
google已经找到了很多关于散列和开放寻址之类的解释,但是没有解决这个问题。
最佳答案
粗略地说,有一个函数,我们称它为F
,它计算值数组中的索引F(h)
。因此这些值被存储为一个数组,并被查找为F(h)
。它“粗略地说”的原因是,对于不同的对象,散列的计算方式是不同的。例如,对于指针,它是p>>3
;而对于字符串,哈希是字符串所有字节的摘要。
如果您想查看C代码,请搜索lookdict_index
或查看CPython源代码中的dictobject.C文件。如果你习惯于阅读C代码的话,它是相当可读的。
编辑1:
在Python 3.6.1的Include/dictobject.h中的注释中:
/* If ma_values is NULL, the table is "combined": keys and values
are stored in ma_keys.
If ma_values is not NULL, the table is splitted:
keys are stored in ma_keys and values are stored in ma_values */
以及dictobject的解释
/*
The DictObject can be in one of two forms.
Either:
A combined table:
ma_values == NULL, dk_refcnt == 1.
Values are stored in the me_value field of the PyDictKeysObject.
Or:
A split table:
ma_values != NULL, dk_refcnt >= 1
Values are stored in the ma_values array.
Only string (unicode) keys are allowed.
All dicts sharing same key must have same insertion order.
....
*/
这些值或者存储为字符串数组,该数组紧跟“键对象”数组。或者每个值的指针都存储在
me_value
的PyDictKeyEntry
中。这些键存储在me_key
的PyDictKeyEntry
字段中。键数组实际上是一个PyDictKeyEntry
结构数组。作为参考,
PyDictKeyEntry
定义为: typedef struct {
/* Cached hash code of me_key. */
Py_hash_t me_hash;
PyObject *me_key;
PyObject *me_value; /*This field is only meaningful for combined tables*/
} PyDictKeyEntry;
要查看的相关文件:Objects/dict common.h、Objects/dictobject.c和Python源代码中的Include/dictobject.h。
Objects/dictobject.c在文件开头的注释中对整个方案和历史背景进行了详细的说明。