Python-List内部实现
Python有很大实现的版本,像拿C语言实现的Cpython,以及在其基础上改进其解释执行变为即时编译(jit)的Pypy,还有一些其他的比如Jpython等。具体来说
其中使用c语言开发的叫做python,在于别的语言开发的python对比时为避免歧义通常称为CPython。同样的,使用java开发的叫做JPython,使用.net开发的叫做IronPython。
- CPython:是用C语言实现Pyhon,是目前应用最广泛的解释器。最新的语言特性都是在这个上面先实现,基本包含了所有第三方库支持
但是CPython有几个缺陷,一是(GIL)全局锁使Python在多线程效能上表现不佳,二是CPython无法支持JIT(即时编译),导致其执行速度不及Java和Javascipt等语言。 - Pypy:是用Python自身实现的解释器。针对CPython的缺点进行了各方面的改良,性能得到很大的提升。最重要的一点就是Pypy集成了JIT。但是,Pypy无法支持官方的C/Python API,导致无法使用例如Numpy,Scipy等重要的第三方库。
那么这次看的list的实现也是看的Cpython的实现,具体链接可以看这两个
头文件的定义listobject.h和具体的实现listobject.c
总的来说,list和STL里面的vector很像,都是基于动态数组dynamic array来实现,这样的好处呢都是方便扩容。
整体的结构定义
list的结构被定义在一个结构体中,该结构体包含有3个elment:
- PyObject_VAR_HEAD:只要头部是PyObject_VAR_HEAD或者PyObject_HEAD的都可以看作PyObject的子类
- PyObject **ob_item:指向具体元素的指针
- Py_ssize_t allocated:allocated标明了此刻list的大小,当我们使用len()方法的时候,该方法获取list的size,以O(1)的时间复杂度返回该值
初始化list
初始化list的时候,为了后续追加元素的方便呢,一般都会初始化一个size大小的动态数组
append
假设我们append一个新的element
一直append就会追加,指针像后移动就ok
当list满了的时候就需要动态扩容数组,一般是扩容为原来的2倍大小
insert
insert操作在上图可以看出一些端倪,比如我们insert(1,5),即在第一个位置插入5的时候
这个时间复杂度是O(n)的一个复杂度,因为它需要一个个的修改内存地址中对应的地址指向的值
pop
pop操作的时间负责度也是O(n),pop一般是pop最后面的元素,同样也需要O(n)的一个时间复杂度
同时,pop之后会调用list_resize函数,如果新的list大小小于原来的一半的话,这时候就会收缩列表
remove
remove操作的时间复杂度也是O(n),移除元素,修改原位置指针所指向的值