首页 > 代码库 > 《python源码剖析》笔记 python中的整数对象

《python源码剖析》笔记 python中的整数对象

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie


1. PyIntObject --> long的一个简单包装

typedef struct{
		PyObject_HEAD
		long ob_ival;
} PyIntObject;

PyInt_Type --> PyIntObject的类型对象。与对象相关的元信息实际上都是保存在与对象对应的类型对象中的
PyTypeObject PyInt_Type = {
		PyObject_HEAD_INIT(&PyType_Type)
		0,
		“int”,
		//…
}

PyIntObject 所支持的操作
int_dealloc  //删除 PyIntObject 对象 
int_free  //删除 PyIntObject 对象 
int_repr  //转化成 PyString 对象 
int_hash  //获得 HASH 值 
int_print  //打印 PyIntObject 对象 
int_compare  //比较操作 
int_as_number  //数值操作 
int_methods  //成员函数
PyIntObject是定长对象,不可变对象 --> 因为不可变,所以对象池里的每一个PyIntObject对象都能够被任意地共享,不用担心被修改。

2. PyIntObject对象的创建和维护
Python C API创建PyIntObject的三种途径
PyObject *PyInt_FromLong(long ival)
PyObject *PyInt_FromString(char *s, char **pend, int base)
#ifdef Py_USING_UNICODE
	PyObject *PyInt_FromUnicode(Py_Unicode *s, int length, int base)
#endif
PyInt_FromString和PyInt_FromUnicode利用了设计模式中的Adaptor Pattern思想对整数对象的核心创建函数PyInt_FromLong进行了接口转换


3. 整数对象池
小整数对象--> 缓存池缓存
大整数对象--> 专用内存池轮流使用
小整数对象与大整数对象的分界点
#ifndf NSMALLPOSINTS
		#define NSMALLPOSINTS	257
#endif
#ifndef NSMALLNEGINTS
		#define NSMALLNEGINTS	5
#endif
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
		static PyIntObject *small_ints[NSMALLPOSINTS + NSMALLPOSINTS];
#endif
3.1 通用整数对象池(大整数对象池)
PyIntBlock的结构
#define BLOCK_SIZE 1000    /* 1K less typical malloc overhead */
#define BHEAD_SIZE 8    /* Enough for a 64-bit pointer */
#define N_INTOBJECTS ((BLOCK_SIZE - BHEAD_SIZE) / 
sizeof(PyIntObject))
struct _intblock {
struct _intblock *next;
PyIntObject objects[N_INTOBJECTS];
};
typedef struct _intblock PyIntBlock;
static PyIntBlock *block_list = NULL;//维护PyIntBlock的单向列表
static PyIntObject *free_list = NULL;//管理全部block的objects中的所有空闲内存
PyInt_FromLong函数
1. 如果小整数对象池机制被激活,则尝试使用小整数对象池
2. 如果还能使用小整数对象池由使用通用的整数对象池。
fill_free_list
1. 申请一个新的PyIntBlock结构
2. 将objects中的所有PyIntObject对象通过指针依次连接起来,形成一个free_list为表头的链表
tp_dealloc
一个PyIntObject对象被销毁时,它所占有的内存并不会被系统释放,而是变成了自由内存被链入了free_list所维护的自由内存链表

问题:ob_type不是用来指向类型对象的吗,在fill_free_list中它却被用来形成链表,那谁来指向类型对象,没有类型对象又怎么调用类型对应的操作?为什么要形成链表?
解析:在fill_free_list中,申请的PyIntBlock空间中的objects(即PyIntObject数组)还没有初始化,即没有被使用,ob_type放着没用,所以可以用来形成链表。当创建新的PyIntBlock时,ob_type会指向PyInt_Type。这里不知道我的理解对不对,如果我的理解对的话,书上的图2-7就有问题,已经创建了的PyIntBlock不应该有一个指向自由内存空间的指针,只有当它被销毁才会重新指向自由内存空间
形成的链表主要是用来维护还没有objects中空闲的内存块,链表的表头由free_list所指向。
3.2 小整数对象池
在pythonrun.c(python环境初始化时)中调用_PyInt_Init函数完成小整数对象池的初始化。



4. Hack PyIntObject
自己实验的结果: