python列表属于什么类型的游戏_python对象类型-List

1 对象原型

typedef struct {

PyObject_VAR_HEAD

PyObject **ob_item;

Py_ssize_t allocated;

} PyListObject;

1.1 PyObject_VAR_HEAD

PyObject_VAR_HEAD是之前讲过的变量类型PyVarObject的宏定义,表明list是一个变量类型。

1.2 ob_item

ob_item是指向PyObject类型的指针的指针。首先说明一下,list是一个容器,里面可以容纳很多PyObject类型的对象。PyListObject用来维护list对象本身的信息,ob_item指向一块连续空间,这块空间装载了n个指针,每一个指针指向一个PyObject对象。

由此可见:List里面并没有真的装载数据,只是在要保存的对象上添加了一条引用。

ob_item的数据结构是顺序表。这决定了list类型insert操作是耗时的操作。

数据大小一致,存储在连续的内存空间中,这种存储结构是顺序表。不同的数据结构,同样的操作性能是不相同的,因此要有不同的算法。

顺序表和链表比起来,通过位置找数据是非常快的,但是插入删除某一节点的开销非常大,需要搬移大块数据。但是顺序表结构简单,占用内存空间小,在list中使用这种结构还是很好的。

Tip:不懂顺序表的自行学习一下,这对于理解list太重要了。“算法+数据结构=程序”至理名言啊

1.3 allocated

allocated表明当前为ob_item分配了多少空间,有别于ob_size,ob_size是当前真正使用了多少空间,这里简单说一下,当你的list变得更长时,每次为ob_item分配空间,并非按需分配,详见list_resize

2 方法

前面我们说过了list对象原型,和使用的数据结构,list的方法主要就是操作list中的数据。核心就是围绕ob_item指向的顺序表展开的。

2.1 list的创建

PyObject *

PyList_New(Py_ssize_t size)

{

PyListObject *op;

#ifdef SHOW_ALLOC_COUNT

static int initialized = 0;

if (!initialized) {

Py_AtExit(show_alloc);

initialized = 1;

}

#endif

if (size < 0) {

PyErr_BadInternalCall();

return NULL;

}

if (numfree) {

numfree--;

op = free_list[numfree];

_Py_NewReference((PyObject *)op);

#ifdef SHOW_ALLOC_COUNT

count_reuse++;

#endif

} else {

op = PyObject_GC_New(PyListObject, &PyList_Type);

if (op == NULL)

return NULL;

#ifdef SHOW_ALLOC_COUNT

count_alloc++;

#endif

}

if (size <= 0)

op->ob_item = NULL;

else {

op->ob_item = (PyObject **) PyMem_Calloc(size, sizeof(PyObject *));

if (op->ob_item == NULL) {

Py_DECREF(op);

return PyErr_NoMemory();

}

}

Py_SIZE(op) = size;

op->allocated = size;

_PyObject_GC_TRACK(op);

return (PyObject *) op;

}

首先说一下,list也有自己的缓冲机制,缓冲池可以容纳80个list对象,对象使用完毕后不会直接销毁,如果缓冲池没有满,就放入缓冲池中,以后新建对象的时候优化使用缓冲池中的对象。这样省去申请内存的开销,用空间换时间。

创建过程:从缓冲池中获取一个对象,如果没有空闲对象则申请一块空间,作为新对象。

为ob_item分配一块指定大小的空间,用来装指针。

维护allocated等其它属性。

2.2 list的插入

int

PyList_Insert(PyObject *op, Py_ssize_t where, PyObject *newitem)

{

if (!PyList_Check(op)) {

PyErr_BadInternalCall();

return -1;

}

return ins1((PyListObject *)op, where, newitem);

}

static int

ins1(PyListObject *self, Py_ssize_t where, PyObject *v)

{

Py_ssize_t i, n = Py_SIZE(self);

PyObject **items;

if (v == NULL) {

PyErr_BadInternalCall();

return -1;

}

if (n == PY_SSIZE_T_MAX) {

PyErr_SetString(PyExc_OverflowError,

"cannot add more objects to list");

return -1;

}

if (list_resize(self, n+1) < 0)

return -1;

if (where < 0) {

where += n;

if (where < 0)

where = 0;

}

if (where > n)

where = n;

items = self->ob_item;

for (i = n; --i >= where; )

items[i+1] = items[i];

Py_INCREF(v);

items[where] = v;

return 0;

}

插入过程:

1将要插入的位置以下所有数据下移

2空出位置插入新数据

2.3 list的删除, 修改, 查询

这个留给读者自行学习吧。读懂了insert,这些也都是小case。

3 other

3.1 List最大容量

大家不要以为,list是无穷大的,在阅读代码的时候我们发现。Python已经规定了list的最大容量PY_SSIZE_T_MAX。

#define PY_SSIZE_T_MAX ((Py_ssize_t)(((size_t)-1)>>1))

(size_t)-1在c语言中表示0xFFFFFFFF。用来表示全1

那么你知道最大值是多少了吗?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值