标签:des style class blog code http
本文为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_smalltablestatic 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为NULLstatic 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)
}《python源码剖析》笔记 python中的Dict对象,布布扣,bubuko.com
标签:des style class blog code http
原文地址:http://blog.csdn.net/zhengsenlie/article/details/31015433