《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) #endifPyInt_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]; #endif3.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函数完毕小整数对象池的初始化。
自己实验的结果:
浙公网安备 33010602011771号