我知道在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_valuePyDictKeyEntry中。这些键存储在me_keyPyDictKeyEntry字段中。键数组实际上是一个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在文件开头的注释中对整个方案和历史背景进行了详细的说明。

09-20 22:38