整数被创建为 PyIntObject (类)的实例.
整数对象是一种不可变对象 (immutable), 即一旦创建, 该对象内部的那个 ival 值不变化.
Python 中 string 也是不可变对象. (ruby 中 string 是可变的...)
整数使用频繁, 即 new/delete 很频繁, 如何提高效率? --- python 使用对象缓冲池机制.
PyIntObject 的元信息见文件 intobject.c.
整数做加法时, 如果溢出会产生 PyLongObject.
(其它略...)
创建整数的 3 条途径(简单了解一下即可, 细节略):
1. PyInt_FromLong(long ival)
2. PyInt_FromString(char *s ...)
3. PyInt_FromUnicode(UNICODE ...)
对于小整数对象被放到对象池中. 这样(它们)就不需要频繁的 malloc/free 了.
这个小整数对象池在初始化函数 _PyInt_Init() 中实现.
对于大整数对象, Python 提供一块内存空间, 由它们轮流使用. 在 intobject.c 中.
struct PyInt_Block { PyInt_Block *next; // 构成链表. PyIntObject objects[NUM_OF_INTOBJS]; // 可以放数个整数对象. } PyInt_Block *block_list; // 维护整个 _intblock 链表. PyIntObject *free_list; // 指向第一个可分配的 int 对象.
所以 这里是一种典型的小块内存分配策略. (因此细节不用再看了)
=================================================================
前面 int 对象是固定长度的对象, 本章学习的 string 对象是变长的(var-size), 但内容是不可变的(immutable).
对应 string 的类为 PyStringObject:
struct PyStringObject { int ref_count; PyType_Object *ob_type; // = &PyString_Type. int ob_size; // 以上是 PyVarObject 头部, 下面是 string 对象数据. int ob_shash; // 缓存此字符串的 hash 值. int ob_sstate; // interned 标志. char ob_sval[1]; // 变长的字符串数据在这里, 包含 ob_size+1 个元素, 以 \0 结束. };
根据结构看, ob_sval[] 是变长数组, 预计是根据字符串长度动态分配这个对象大小的.
Python 内部所有变长对象使用 ob_size 机制.
Python 注释显示, 预存字符串 hash 值和 intern 机制将 python 虚拟机的执行效率提升了 20%. (空间换时间)
PyString_Type 中 tp_as_number, tp_as_sequence, tp_as_mapping 都被设置, 故而 string 支持这三种操作.
类似于 int 对象, 函数 PyObject *PyString_FromString(const char *str) 可创建一个 Python 字符串对象.
别的类似函数可看做不同的 String 构造函数.
Python 对长度为 0,1 的字符串提供特别动作: intern. (书上翻译为 `共享', 有的地方翻译为 `拘留' ...)
实现为使用一个内部(static的) dict 来保存所有 interned 字符串, 该 string 同时作为 key 和 value 在 dict 中.
Python 对单个字符的字符串也提供了对象池. (stringobject.c 用 characters[UCHAR_MAX+1] 数组实现)
用 '+' 运算符连接字符串在 Python 中极其低效, 官方推荐做法用 string.join() 进行连接操作.
方法是先计算总的所需空间, 然后一次性分配结果字符串, 然后复制...
=================================================================
PyListObject 是 Python 提供的列表实现类. 与 STL 中的 vector 比较相似.
可看作是 vector<PyObject *>, 可插入, 添加, 删除元素.
struct PyListObject { PyObject_VAR_HEAD; // 变长 Python 对象头部. ob_size 应是元素数量. PyOjbect **ob_item; // 列表实现. int allocated; // 总容量 (capacity). };
根据字段看, 是类似于 vector 的机理.
函数 PyList_New() 用于创建 list 对象. (可看做是 PyListObject.ctor() 构造函数).
内部使用一个大小为 MAXFREELISTS(=80) 的数组做对象池, 以减少 malloc/free 调用.
列表的对象 get/set[index], insert(), append(), remove() 等方法实现与 vector 相似, 因此细节略.
即 free_lists[] 数组的维护.
(本篇 END, 下次接着学习)