在5.5节中,第一个实验中,我使用的是Python2.7.13,和书中的一些类型的定义有些不同:
/*****************Test Func*********************/
// dictobject.c 自定义的函数
static void
ShowDictObject(PyDictObject* dictObject)
{
PyDictEntry* entry = dictObject->ma_table;
int count = dictObject->ma_mask+1;
int i;
// 输出key
printf(" key : ");
for(i=0;i<count;++i){
PyObject* key = entry->me_key;
PyObject* value = entry->me_value;
if(key == NULL){
printf("NULL");
}else{
if(PyString_Check(key)){
if(PyString_AsString(key)[0] == '<'){
printf("dummy");
}else{
(key->ob_type)->tp_print(key, stdout, 0);
}
}else{
(key->ob_type)->tp_print(key, stdout, 0);
}
}
printf("\t");
++entry;
}
// 输出value
printf("\nvalue : ");
entry = dictObject->ma_table;
for(i=0;i<count;++i){
PyObject* key = entry->me_key;
PyObject* value = entry->me_value;
if(value == NULL){
printf("NULL");
}else{
(key->ob_type)->tp_print(value, stdout, 0);
}
printf("\t");
++entry;
}
printf("\n");
}
/*****************Test Func*********************/
另外,在Py2.7中,insertdict外新增了一个函数insertdict_by_entry:
static int
insertdict(register PyDictObject *mp, PyObject *key, long hash, PyObject *value)
{ // hash值参数是在调用insertdict之前,先调用PyDict_SetItem获得hash值。
register PyDictEntry *ep;
assert(mp->ma_lookup != NULL);
ep = mp->ma_lookup(mp, key, hash);
if (ep == NULL) {
// 搜索失败,收回传入参数的引用计数
Py_DECREF(key);
Py_DECREF(value);
return -1;
}
// 搜索成功
return insertdict_by_entry(mp, key, hash, ep, value);
}
而调用我们自定义的函数ShowDictObject则是在insertdict_by_entry中进行:
static int
insertdict_by_entry(register PyDictObject *mp, PyObject *key, long hash,
PyDictEntry *ep, PyObject *value)
{
PyObject *old_value;
/*****************Test Func*********************/
PyDictEntry* p;
long strHash;
PyObject* str = PyString_FromString("PR");
/*****************Test Func*********************/
MAINTAIN_TRACKING(mp, key, value);
if (ep->me_value != NULL) {
// active态
// 属性赋值以及引用减一
old_value = ep->me_value;
ep->me_value = value;
Py_DECREF(old_value); /* which **CAN** re-enter */
Py_DECREF(key);
}
else {
if (ep->me_key == NULL)
// Unused态
// 插入后变成active态,ma_fill++
// ma_fill = active + dummy
mp->ma_fill++;
else {
assert(ep->me_key == dummy);
// dummy态
// 插入后dummy的引用减一
Py_DECREF(dummy);
}
// 属性赋值
ep->me_key = key;
ep->me_hash = (Py_ssize_t)hash;
ep->me_value = value;
mp->ma_used++;
}
/*****************Test Func*********************/
strHash = PyObject_Hash(str);
p = mp->ma_lookup(mp, str, strHash);
if(p->me_value != NULL && (key->ob_type)->tp_name[0] == 'i'){
PyIntObject* intObject = (PyIntObject*)key;
printf("insert %d\n", intObject->ob_ival);
ShowDictObject(mp);
}
/*****************Test Func*********************/
return 0;
}
其中的注意点是,变量在开头声明,以及代码段应该写在插入操作后面,不然输出的效果实际上是前一次操作的结果,最后结果如图: