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),移除元素,修改原位置指针所指向的值

posted @ 2020-09-16 22:53  real-zhouyc  阅读(757)  评论(0编辑  收藏  举报