看书 Python 源码分析笔记 (二)

第二章 Python 中的整数对象

初识 PyIntObject 对象

整数被创建为 PyIntObject (类)的实例.
整数对象是一种不可变对象 (immutable), 即一旦创建, 该对象内部的那个 ival 值不变化.
Python 中 string 也是不可变对象. (ruby 中 string 是可变的...)

整数使用频繁, 即 new/delete 很频繁, 如何提高效率? --- python 使用对象缓冲池机制.

PyIntObject 的元信息见文件 intobject.c.

整数做加法时, 如果溢出会产生 PyLongObject.

(其它略...)

 

PyIntObject 对象的创建和维护

创建整数的 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 对象.

 

所以 这里是一种典型的小块内存分配策略. (因此细节不用再看了)


=================================================================

第三章 Python 中的字符串对象

前面 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 支持这三种操作.

 

创建 PyStringObject 对象

类似于 int 对象, 函数 PyObject *PyString_FromString(const char *str) 可创建一个 Python 字符串对象.
别的类似函数可看做不同的 String 构造函数.

字符串对象的 intern 机制

Python 对长度为 0,1 的字符串提供特别动作: intern. (书上翻译为 `共享', 有的地方翻译为 `拘留' ...)

实现为使用一个内部(static的) dict 来保存所有 interned 字符串, 该 string 同时作为 key 和 value 在 dict 中.

字符缓冲池

Python 对单个字符的字符串也提供了对象池. (stringobject.c  用 characters[UCHAR_MAX+1] 数组实现)

 

PyStringObject 效率相关问题

用 '+' 运算符连接字符串在 Python 中极其低效, 官方推荐做法用 string.join() 进行连接操作.
方法是先计算总的所需空间, 然后一次性分配结果字符串, 然后复制...

 

=================================================================

第四章 Python 中的 List 对象

PyListObject 是 Python 提供的列表实现类. 与 STL 中的 vector 比较相似.

PyListObject 对象

可看作是 vector<PyObject *>, 可插入, 添加, 删除元素.

struct PyListObject {
  PyObject_VAR_HEAD;   // 变长 Python 对象头部. ob_size 应是元素数量.
  PyOjbect **ob_item;  // 列表实现. 
  int allocated;       // 总容量 (capacity).
};

根据字段看, 是类似于 vector 的机理.

PyListObject 对象的创建与维护

函数 PyList_New() 用于创建 list 对象. (可看做是 PyListObject.ctor() 构造函数).

内部使用一个大小为 MAXFREELISTS(=80) 的数组做对象池, 以减少 malloc/free 调用.

列表的对象 get/set[index], insert(), append(), remove() 等方法实现与 vector 相似, 因此细节略.

PyListObject 对象缓冲池

即 free_lists[] 数组的维护.

 

(本篇 END, 下次接着学习)

你可能感兴趣的:(看书 Python 源码分析笔记 (二))