本系列作为本人@takooctopus深入学习python机制的记录,这个博客遵照着栖迟于一丘的博客上面的流程进行的,也包含我在实际查看源码时的感想,特此列出,表示感谢。
关于List对象
我们首先去[Include/listobject.h]
中去寻找列表对象的定义:
{{- code -}}
其中有三个属性,PyObject_VAR_HEAD
是指向了一个list元素,以及一个二级指针**ob_item
储存了这个指针的地址。还有一个allocated
储存分配的内存大小。
{{- code -}}
我们可以看见PyObject_VAR_HEAD
指向了一个PyVarObject
,即其指向了这个元素的第一个,我们通俗地看就是list[0]
就是ob_item[0]
。
我们看指向的PyVarObject
,其中的属性ob_size
就代表了当前列表的个数len(list)
。
我们要注意的是,其会申请一块较大的内存,及我们有0 <= ob_size <= allocated
关系。
但当列表元素为NULL
时,整个内存分配会直接降为0
,此时有,ob_size == allocated == 0
PyListObject 方法
我们可以看见在这个Object
类中的方法:
{{- code -}}
PyListObject的创建
列表的创建我们使用的是PyList_New()
:
{{- code -}}
我们在这里看见了numfree
这个属性,返回去看,发现其与一个列表free_list[]
有关,称其为freelist
,也可以叫其为缓冲池。其常量定义在最前面:
{{- code -}}
在缓冲池有剩余时,新建一个list
对象,会直接从缓冲区freelist[]
中直接初始化,缓冲池不可用的时候,就会调用PyObject_GC_New()
直接新建。
默认情况下,缓冲区最大有PyList_MAXFREELIST = 80
个对象。
PyObject_GC_New()
是_PyObject_GC_New()
的别名:
{{- code -}}
其为这个对象类型分配内存。
而关于缓冲区freelist[]
的函数其实只有三个,另外俩一个是PyList_ClearFreeList()
,用以清除所有的缓冲区;还有一个是list_dealloc()
,其作用是PyListType
对象的析构操作。
奇怪的是,其会在释放掉PyListObject *op
中维护的所有对象后,视情况将其放入缓冲区或者直接释放掉。这应该是为了保证缓冲区在结束后有足够的大小。
PyListObject的元素设置
{{- code -}}
在进行了类型和越界检查后,平移指针找到需要替换的位置,替换为新的对象。在Py_XSERREF()
中我们能看见其将原本对象的引用进行检查,必要时施行销毁操作。
PyListObject获取元素
{{- code -}}
PyListObject的插入操作
{{- code -}}
简单地处理了插入时的越界和负索引「如果负索引过小于-n
会直接置零」后,确定插入位置,后面的元素统一后移一个位置。
PyListObject的附加操作
{{- code -}}
和上面的添加操作差不多
PyListObject的删除操作
{{- code -}}
python会在遍历列表后删除找到第一个匹配的元素,并在找不到时返回异常。
其他操作
此外PyListObject还有很多方法,比如merge
相关,reverse
相关和sort
相关等等,这些在以后再写。