五、从PyIntObject出发
来源:互联网 发布:sql distinct一个字段 编辑:程序博客网 时间:2024/05/17 07:45
1.初识PyIntObject
本节要说的内容是“整数”,我们来看看这个PyInt_Type变量,这个变量里面大量的元信息是我们要关注的。它描述了一个整数对象。
[intobject.c]PyTypeObject PyInt_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "int", sizeof(PyIntObject), //对象占用内存大小 0, (destructor)int_dealloc, /* tp_dealloc */ //对象析构 (printfunc)int_print, /* tp_print */ //打印PyIntObject对象 0, /* tp_getattr */ 0, /* tp_setattr */ (cmpfunc)int_compare, /* tp_compare */ //比较操作 (reprfunc)int_to_decimal_string, /* tp_repr */ &int_as_number, /* tp_as_number */ //一个函数域,描述作为一个number该有的行为 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)int_hash, /* tp_hash */ //获得HASH值 0, /* tp_call */ (reprfunc)int_to_decimal_string, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_INT_SUBCLASS, /* tp_flags */ int_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ int_methods, /* tp_methods */ 0, /* tp_members */ int_getset, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ int_new, /* tp_new */ (freefunc)int_free, /* tp_free */};
各个函数的实现都在intobject.c中,可自行查看。
如:加法代码:
[intobject.h]#define PyInt_AS_LONG(op) (((PyIntObject *)(op))->ob_ival)[intobject.c]#define CONVERT_TO_LONG(obj, lng) \ if (PyInt_Check(obj)) { \ lng = PyInt_AS_LONG(obj); \ } \ else { \ Py_INCREF(Py_NotImplemented); \ return Py_NotImplemented; \ }static PyObject *int_add(PyIntObject *v, PyIntObject *w){ register long a, b, x; CONVERT_TO_LONG(v, a); CONVERT_TO_LONG(w, b); /* casts in the line below avoid undefined behaviour on overflow */ x = (long)((unsigned long)a + b); //溢出检查 if ((x^a) >= 0 || (x^b) >= 0) return PyInt_FromLong(x); return PyLong_Type.tp_as_number->nb_add((PyObject *)v, (PyObject *)w);}
2.PyIntObject的创建和维护
对象创建三种途径:
[intobject.h]PyAPI_FUNC(PyObject *) PyInt_FromLong(long);PyAPI_FUNC(PyObject *) PyInt_FromSize_t(size_t); //实际上调用的是PyInt_FromFloatPyAPI_FUNC(PyObject *) PyInt_FromSsize_t(Py_ssize_t);//实际上调用的是PyInt_FromFloat
我们主要讨论:PyInt_FromLong
------------------------------------割,以下讨论整数的存储形式,及方案------------------------------------
小整数对象使用对象池技术:Python直接将这些整数对应的PyIntObject缓存在内存中,其指针放在small_ints中
[intobject.c]#ifndef NSMALLPOSINTS#define NSMALLPOSINTS 257#endif#ifndef NSMALLNEGINTS#define NSMALLNEGINTS 5#endif#if NSMALLNEGINTS + NSMALLPOSINTS > 0/* References to small integers are saved in this array so that they can be shared. The integers that are saved are those in the range -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).*/static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];#endif
大整数对象Python运行环境将提供一块内存空间,这些内存空间由这些大整数轮流使用。
[intobject.c]#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;static PyIntObject *free_list = NULL;
通用整数对象池的创建:
[intobject.c]static PyIntObject *fill_free_list(void){ PyIntObject *p, *q; /* Python's object allocator isn't appropriate for large blocks. */ p = (PyIntObject *) PyMem_MALLOC(sizeof(PyIntBlock));//申请一块block的内存 if (p == NULL) return (PyIntObject *) PyErr_NoMemory(); ((PyIntBlock *)p)->next = block_list;//连接到已有的block_list中,大家非常熟悉的头接法 block_list = (PyIntBlock *)p; //重新把block_list置为头部 /* Link the int objects together, from rear to front, then return the address of the last int object in the block. */ p = &((PyIntBlock *)p)->objects[0]; q = p + N_INTOBJECTS; while (--q > p) Py_TYPE(q) = (struct _typeobject *)(q-1); Py_TYPE(q) = NULL; return p + N_INTOBJECTS - 1;}[ctypes.h]#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
效果如图:
通用整数对象池的使用:
[intobject.c]static voidint_dealloc(PyIntObject *v){ if (PyInt_CheckExact(v)) { Py_TYPE(v) = (struct _typeobject *)free_list; free_list = v; } else Py_TYPE(v)->tp_free((PyObject *)v);}
小整数对象池的创建:
[intobject.c]int_PyInt_Init(void){ PyIntObject *v; int ival;#if NSMALLNEGINTS + NSMALLPOSINTS > 0 for (ival = -NSMALLNEGINTS; ival < NSMALLPOSINTS; ival++) { if (!free_list && (free_list = fill_free_list()) == NULL) return 0; /* PyObject_New is inlined */ v = free_list; free_list = (PyIntObject *)Py_TYPE(v); PyObject_INIT(v, &PyInt_Type); v->ob_ival = ival; small_ints[ival + NSMALLNEGINTS] = v; }#endif return 1;}
创建后效果如图:事实上,小整数对象也是生存在block_list所维护的内存上
------------------------------------割,以上讨论整数的存储形式,及方案------------------------------------
现在存储有了,让我们来看看PyInt_FromLong,具体如何创建一个PyIntObject
[intobject.c]PyObject *PyInt_FromLong(long ival){ register PyIntObject *v;#if NSMALLNEGINTS + NSMALLPOSINTS > 0//如果小整数对象池被激活,尝试使用小整形对象池 if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) { v = small_ints[ival + NSMALLNEGINTS]; Py_INCREF(v);#ifdef COUNT_ALLOCS if (ival >= 0) quick_int_allocs++; else quick_neg_int_allocs++;#endif return (PyObject *) v; }#endif//木有办法了,大整形,只好用通用的整数对象池了//对象池木有空间,新申请 if (free_list == NULL) { if ((free_list = fill_free_list()) == NULL) return NULL; } /* Inline PyObject_New */ v = free_list; free_list = (PyIntObject *)Py_TYPE(v); PyObject_INIT(v, &PyInt_Type); v->ob_ival = ival; return (PyObject *) v;}
- 五、从PyIntObject出发
- 开发,从需求出发 · 之五 麦克斯韦妖
- 从C出发
- SDT从这里出发
- WF从O出发
- 从这里出发
- 就从这里出发
- 从这里出发
- 从内核出发
- 从这里出发
- 从这里出发
- 持之以恒,从心出发
- 从Token出发
- 从这里出发
- 从心出发,从零开始
- 从心出发
- 从《网安法》出发_给企业安全管理者的五条建议
- 从《网安法》出发_给企业安全管理者的五条建议
- Spring Framework 开发参考手册 - Spring Framework reference 2.0.5 参考手册中文版
- 《Android系统学习》第九章:Android模拟器编译
- Linux ALSA声卡驱动之五:移动设备中的ALSA(ASoC)
- 浅谈Android的TabHost(二)
- iOS笔记——遍历Tableview
- 五、从PyIntObject出发
- kexec
- Facebook的毁灭者---HTML5!
- Linux ALSA声卡驱动之六:ASoC架构中的Machine
- 取消outlook正在发送的邮件
- 【phpcms-v9】怎样在<script src="xxx.php"></script>标记中引入php文件
- css 点击超级链接时,去掉周围的虚线框
- 卷i 第九章
- Excel 2007中数据分析功能详解