上QQ阅读APP看书,第一时间看更新
3.1.1 序列对象解析
Python提供的列表的抽象对象为PyListObject,即List对象。List对象是一个变长对象,在运行时动态调整其所维护的内存和元素,并且支持插入、删除等操作。
PyListObject对象源码(Include/listobject.h)结构如下:
// Include/listobject.h typedef struct { PyObject_VAR_HEAD // 变量头部信息 PyObject **ob_item; // 元素指向具体值 Py_ssize_t allocated; // 当前空间 } PyListObject;
结合可变对象的源码(Include/object.h)如下:
// Include/object.h typedef struct _object { _PyObject_HEAD_EXTRA // 双向链表 垃圾回收 需要用到 Py_ssize_t ob_refcnt; // 引用计数 struct _typeobject *ob_type; // 指向类型对象的指针,决定了对象的类型 } PyObject; typedef struct { PyObject ob_base; Py_ssize_t ob_size; /* Number of items in variable part */ } PyVarObject;
上述源码中,ob_size和allocated都和PyListObject对象的内存管理有关。ob_size表示列表实际拥有的元素数量,allocated表示实际申请的内存空间,比如列表A实际申请了5个元素的空间,但此时A只包含2个元素,则ob_size为2,allocated为5。
生成新的List对象时,首先检查缓冲池是否有List对象,若没有,则新生成一个List对象。新建的List对象默认维护80个PyListObject对象,源码(Object/Listobject.c)如下:
// Object/listobject.c #define PyList_MAXFREELIST 80 #endif static PyListObject *free_list[PyList_MAXFREELIST]; static int numfree = 0;
每次对序列对象添加元素时,都会调整列表的大小。在调整列表大小后,如果传入的负值索引比列表长度还大,则传入值设置在0位;如果传入的正值索引比列表长度还大,则传入值设置为最后一位,并将大于索引值的元素往后移动一位。这就是序列插入的大致过程。
这里对序列的源码做一些简单讲解,对序列源码感兴趣的读者可以重点查看Include/listobject.h和Object/listobject.c这两个文件。序列的创建、插入、删除、调整等的源码实现都在Object/listobject.c文件中。