本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie
1.PyDictObject对象 --> C++ STL中的map是基于RB-tree的,搜索时间复杂度是O(logN)
PyDictObject采用了hash表,时间复杂度是O(1)
typedef struct{ Py_ssize_t me_hash; //me_key的hash值,避免每次查询都要重新计算一遍hash值 PyObject *me_key; PyObject *me_value; }PyDictEntry;
typedef struct _dictobject PyDictObject; struct _dictobject{ PyObject_HEAD Py_ssize_t ma_fill; //元素个数: Active + Dummy Py_ssize_t ma_used; //元素个数: Active Py_ssize_t ma_mask; //记录了entry的数量 PyDictEntry *ma_table; PyDictEntry *(*ma_lookup)(PyDictObject *mp, PyObject *key, long hash); PyDictEntry ma_smalltable[PyDict_MINSIZE]; }
PyTypeObject PyDict_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "dict", sizeof(PyDictObject), 0, (destructor)dict_dealloc, /* tp_dealloc */ (printfunc)dict_print, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ (cmpfunc)dict_compare, /* tp_compare */ (reprfunc)dict_repr, /* tp_repr */ 0, /* tp_as_number */ &dict_as_sequence, /* tp_as_sequence */ &dict_as_mapping, /* tp_as_mapping */ (hashfunc)PyObject_HashNotImplemented, /* tp_hash */ //... };
PyObject* PyDict_New(void) { register dictobject *mp; //[1]:自动创建 dummy对象 //防止探测序列中断 if (dummy == NULL) { /* Auto-initialize dummy */ dummy = PyString_FromString("<dummy key>"); } if (num_free_dicts) { …… //[2]:使用缓冲池 } else { //[3]:创建 PyDictObject对象 mp = PyObject_GC_New(dictobject, &PyDict_Type); EMPTY_TO_MINSIZE(mp); } mp->ma_lookup = lookdict_string; return (PyObject *)mp; } //EMPTY_TO_MINSIZE --> ma_size, ma_fill = 0 //INIT_NONZERO_DICT_SLOT --> 将 ma_table指向 ma_smalltable
static PyDictEntry * lookdict(PyDictObject *mp, PyObject *key, register long hash) { register size_t i; register size_t perturb; register PyDictEntry *freeslot; //freeslot用来指向探测序列中第一个处于Dummy态的entry register size_t mask = (size_t)mp->ma_mask; PyDictEntry *ep0 = mp->ma_table; register PyDictEntry *ep; register int cmp; PyObject *startkey; //[1]:hash,定位冲突探测链的第一个entry i = (size_t)hash & mask; //将哈希值映射到哈希表大小范围内 ep = &ep0[i]; //[2]: //1. entry处于Unused态 //2. entry中的 key与待搜索的 key匹配 if (ep->me_key == NULL || ep->me_key == key) //**引用相同检查 return ep; //[3]:第一个entry处于 Dummy态,设置freeslot if (ep->me_key == dummy) freeslot = ep; else { //检查Active态entry if (ep->me_hash == hash) { startkey = ep->me_key; cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);//**值相同检查 if (cmp < 0) return NULL; } freeslot = NULL; } for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { //[5]:寻找探测链上下一个entry i = (i << 2) + i + perturb + 1;//? ep = &ep0[i & mask]; //[6]:到达 Unused态 entry,搜索失败 if (ep->me_key == NULL) //如果 freeslot不为空,返回freeslot所指的entry //如果 freeslot为空,返回该 Unused态的 entry return freeslot == NULL ? ep : freeslot; if (ep->me_key == key) //“引用相同”规则检查 return ep; if (ep->me_hash == hash && ep->me_key != dummy) { // "值相同"规则检查 startkey = ep->me_key; cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); if (cmp > 0) return ep; } else { return lookdict(mp, key, hash); } } else if (ep->me_key == dummy && freeslot == NULL) freeslot = ep; } } //失败或成功返回entry,失败的话,entry的me_value为NULL
static void dict_dealloc(register PyDictObject *mp) { register PyDictEntry *ep; Py_ssize_t fill = mp->ma_fill; //[1]:调整dict中对象的引用计数 for (ep = mp->ma_table; fill > 0; ep++) { if (ep->me_key) { --fill; Py_DECREF(ep->me_key); Py_XDECREF(ep->me_value); } } //[2]:释放从系统堆中申请的内存空间 if (mp->ma_table != mp->ma_smalltable) PyMem_DEL(mp->ma_table); //[3]:将被销毁的PyDictObject对象放入缓冲池 if (numfree < PyDict_MAXFREELIST && Py_TYPE(mp) == &PyDict_Type) free_list[numfree++] = mp; else Py_TYPE(mp)->tp_free((PyObject *)mp); Py_TRASHCAN_SAFE_END(mp) }