[cpyhon源代码]dict对象原理学习
Cpython 2.7 分支中,dict 对象的源代码 lookdict 搜索算法
1 static PyDictEntry * 2 lookdict(PyDictObject *mp, PyObject *key, register long hash) 3 { 4 register size_t i; 5 register size_t perturb; 6 register PyDictEntry *freeslot; 7 register size_t mask = (size_t)mp->ma_mask; 8 PyDictEntry *ep0 = mp->ma_table; 9 register PyDictEntry *ep; 10 register int cmp; 11 PyObject *startkey; 12 13 i = (size_t)hash & mask; 14 ep = &ep0[i]; 15 if (ep->me_key == NULL || ep->me_key == key) //【1】 16 return ep; 17 18 if (ep->me_key == dummy) 19 freeslot = ep; 20 else { 21 //进到这里说明 ep->me-key !=NULL && ep->me_key!=key && ep->me_key==Active 22 if (ep->me_hash == hash) { 23 startkey = ep->me_key; 24 Py_INCREF(startkey); 25 cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); //[2]这里为啥要再比较一次? 26 Py_DECREF(startkey); 27 if (cmp < 0) 28 return NULL; 29 if (ep0 == mp->ma_table && ep->me_key == startkey) {//[3]这里明显是相等的,为啥要再判断一次? 30 if (cmp > 0) 31 return ep; 32 } 33 else { 34 /* The compare did major nasty stuff to the 35 * dict: start over. 36 * XXX A clever adversary could prevent this 37 * XXX from terminating. 38 */ 39 return lookdict(mp, key, hash); 40 } 41 } 42 freeslot = NULL; 43 }
两个问题无法理解:
1.1 dict 对象搜索算法中,进入【2】处已经说明了 ep->me_key!=key 这个条件成立,但是 【2】那里为啥要再次比较一次 me_key 和 key 呢?
百思不得其解!!!
原因: 【1】处为两个指针做 == 比较,说明指针的内容相同,即指向的是同一对象
进入到流程【2】则说明两个对象指向不同的内存,但是在满足两个条件后也认为他们“相等”,从而返回对应的项目,条件如下:
一是 两个对象哈希值相等
二是 两个对象的值相等(比较算法由对象提供,通常是 __eq__方法)
举例:dict[10000]=10,此时需要搜索 d[10000]对象的 entry 对象,搜索时 指向 10000 的Pyobject* 明显和之前 存入 dict[10000] 值时对应的
Pyobject 指针不一致,此时 p(p->int(10000) me_key) != q(q->int(10000) key),因此不会进入流程 【1】
但是 p,q同时满足规定的两个条件,即hash值和 ob_val 都一致,因此返回 p 处的 (key,value)entry
1.2 [3]处 判断的条件明显是成立的(参见蓝色高亮部分),不理解为啥要重复判断一次,暂时想不通~