您的位置:首页 > 编程语言 > Python开发

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

2014-06-13 17:56 260 查看
本文为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

自己实验的结果:

 


 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: