《Python源码剖析》笔记Hack PyDictObject(1)

在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;
}

其中的注意点是,变量在开头声明,以及代码段应该写在插入操作后面,不然输出的效果实际上是前一次操作的结果,最后结果如图:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值