本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie

1.PyListObject对象 --> 变长可变对象,可看作vector<PyObject *>

typedef struct{
PyObject_VAR_HEAD //当中的ob_size表示实际被使用的内存的数量
PyObject **ob_item;//ob_item为指向元素列表的指针,实际上,Python中的list[0]就是ob_item[0]
int allocated;//当前列表中可容纳的元素的总数
}

PyList_Type 对象 --> PyListObject的类型对象

typedef struct{
PyObject_VAR_HEAD //当中的ob_size表示实际被使用的内存的数量
PyObject **ob_item;//ob_item为指向元素列表的指针。实际上,Python中的list[0]就是ob_item[0]
int allocated;//当前列表中可容纳的元素的总数
}

2.创建PyListObject对象

一种途径:

PyObject *PyList_New(int size)

1.内存数量计算,溢出检查

2.为PyListObject对象申请空间

3.为PyListObject对象中维护的元素列表申请空间



PyListObject缓冲池,缓存的仅仅是PyListObject *

#define MAXFREELISTS 80
static PyListObject *free_lists[MAXFREELISTS]
static int num_free_lists = 0;

在第一个PyListObject创建的时候。num_free_lists是0,

会调用 PyObject_GC_New在系统堆上创建一个新的PyListObject对象

当一个PyListObject被销毁时,它会被缓存到PyListObject缓冲池中

假设创建的不是第一个PyListObject时,会检查num_free_lists是否为0。

假设不是的话,在缓冲池中的PyListObject对象会被又一次唤醒,又一次分配PyObject *

元素列表占用内存,而num_free_lists也会对应的减一。



设置元素

int
PyList_SetItem(register PyObject *op, register Py_ssize_t i,
register PyObject *newitem)
{
register PyObject *olditem;
register PyObject **p;
if (!PyList_Check(op)) {
Py_XDECREF(newitem);
PyErr_BadInternalCall();
return -1;
}
//[1]:索引检查
if (i < 0 || i >= Py_SIZE(op)) {
Py_XDECREF(newitem);
PyErr_SetString(PyExc_IndexError,
"list assignment index out of range");
return -1;
}
//[2]:设置元素
p = ((PyListObject *)op) -> ob_item + i;
olditem = *p;
*p = newitem;
Py_XDECREF(olditem);//注意要将旧元素的引用减一。好让GC自己主动回收olditem所指向的内存
//用Py_XDECREF,而不用Py_DECREF是由于olditem有可能是NULL
return 0;
}

插入元素

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;
}
//[1]:调整列表容量
if (list_resize(self, n+1) == -1)
return -1;
//[2]:确定插入点
if (where < 0) {
where += n;
if (where < 0)
where = 0;
}
if (where > n)
where = n;
//[3]:插入元素
items = self->ob_item;
for (i = n; --i >= where; )
items[i+1] = items[i];
Py_INCREF(v); //由于多了一个指向v的指针。所以要添加v的引用数目
items[where] = v;
return 0;
} 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
list_resize(PyListObject *self, Py_ssize_t newsize)
{
PyObject **items;
size_t new_allocated;
Py_ssize_t allocated = self->allocated; //假设newsize < allocated && newsize > allocated/2。就不须要又一次申请内存
if (allocated >= newsize && newsize >= (allocated >> 1)) {
assert(self->ob_item != NULL || newsize == 0);
Py_SIZE(self) = newsize;
return 0;
} new_allocated = (newsize >> 3) + (newsize < 9 ? 3 : 6); /* check for integer overflow */
//... if (newsize == 0)
new_allocated = 0;
//扩展列表
items = self->ob_item;
PyMem_RESIZE(items, PyObject *, new_allocated);//终于调用C中的realloc self->ob_item = items;
Py_SIZE(self) = newsize;
self->allocated = new_allocated;
return 0;
}

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhlbmdzZW5saWU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">



删除元素

比較操作

int PyObject_RichCompareBool(PyObject *v, PyObject *w, int op)

/* a[ilow:ihigh] = v if v != NULL.
* del a[ilow:ihigh] if v == NULL.
* 当v!=NULL时,用v替换a[ilow:ihigh]
* 当v == NULL时,删除a[ilow:ihigh]
*/
static int
list_ass_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v)

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhlbmdzZW5saWU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">



watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhlbmdzZW5saWU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">



3.PyListObject对象缓冲池

static void list_dealloc(PyListObject *op)

1.销毁PyListObject对象维护的元素列表。对list中的每个元素改变其引用计数。然后将内存释放

2.释放PyListObject自身。查看缓存的PyListObject的数量是否已经满了,假设没有,就将该待删除的PyListObject

对象放到缓冲池。以备后用。缓冲的不过PyListObject对象,而没有这个对象以前拥有的PyObject *元素列表



4.Hack PyListObject

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhlbmdzZW5saWU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

《python源代码剖析》笔记 python中的List对象的更多相关文章

  1. Python源代码剖析笔记3-Python运行原理初探

    Python源代码剖析笔记3-Python执行原理初探 本文简书地址:http://www.jianshu.com/p/03af86845c95 之前写了几篇源代码剖析笔记,然而慢慢觉得没有从一个宏观 ...

  2. 《python源代码剖析》笔记 Python的编译结果

    本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.python的运行过程 1)对python源码进行编译.产生字节码 2)将编译结果交给p ...

  3. 《python源代码剖析》笔记 Python虚拟机框架

    本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 1. Python虚拟机会从编译得到的PyCodeObject对象中依次读入每一条字节码指令 ...

  4. 《python源代码剖析》笔记 python环境初始化

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/zhsenl/article/details/33747209 本文为senlie原创.转载请保留此地 ...

  5. Redis源代码剖析和凝视(八)--- 对象系统(redisObject)

    Redis 对象系统 1. 介绍 redis中基于双端链表.简单动态字符串(sds).字典.跳跃表.整数集合.压缩列表.高速列表等等数据结构实现了一个对象系统,而且实现了5种不同的对象,每种对象都使用 ...

  6. 《python源代码剖析》笔记 python虚拟机中的函数机制

    本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.Python虚拟机在运行函数调用时会动态地创建新的 PyFrameObject对象, 这 ...

  7. 《python源代码剖析》笔记 python中的Dict对象

    本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.PyDictObject对象 -->  C++ STL中的map是基于RB-tre ...

  8. Python知识点入门笔记——Python文件操作、异常处理及random模块使用

    文件是存储在外部介质的数据集合,通常可以长久保存,前提是介质不易损坏 Python的绝对路径写法: E:\\编程学习资料\\爬取某社区高清无码大图.py E:/编程学习资料/爬取某社区高清无码大图.p ...

  9. Python知识点入门笔记——Python的基本数据类型

    Python的数字分为4种类型:整数(int).浮点数(float).布尔值(bool).复数(complex). type()函数可以知道数据的类型,如type(233)是int型,type(233 ...

随机推荐

  1. 两次被百度k站两次恢复的亲身经历

    最后,网站被k了并不是最重要的,最重要的是你能不能找到网站被k的病因所在,不知道病因的话,就盲目的优化,恢复起来可能效果就不太明显,也比较浪费时间.只有找到了被k的原因,这样恢复起来才会得心应手,省时 ...

  2. Visual Studio 2013 sqlce 配置(转)

    Visual Studio 2013 把內建 SQL CE 的管理工具拿掉了 下载SQL Server Compact Toolbox by ErikEJ并安装 打开VS2013,新建一工程,在“视图 ...

  3. Arcgis for JavascriptAPI 常用接口

    转自原文arcgis for javascriptAPI常用接口 var map, navToolbar, editToolbar, tileLayer, toolbar; //var mapBase ...

  4. Android开发中,比较有特色的特性(与iOS相比)

    1.界面代码和界面控件元素时时联动.同步 2.当我们创建一个Activity时,系统自动帮我们维护strings.xml 文件和AndroidManifest.xml文件. 3.有来无回,删除.修改时 ...

  5. cocos2d-x基本元素

    from://http://www.cnblogs.com/ArmyShen/p/3239664.html 1.CCDirector(导演类) 控制游戏流程的主要类,主要负责设定游戏窗口.切换场景.暂 ...

  6. oracle11g忘记sys密码

    目  录 1 以管理员身份运行cmd窗口 2 启动sqlplus并敲入一系列命令 3 特别注意 1以管理员身份运行cmd窗口 我安装的是oracle11.2版本,sqlplus.exe所在目录是:I: ...

  7. Linux进程ID号--Linux进程的管理与调度(三)

    转自:http://blog.csdn.net/gatieme/article/category/6225543 日期 内核版本 架构 作者 GitHub CSDN 2016-05-12 Linux- ...

  8. Java删除List和Set集合中元素

    今天在做项目时,需要删除List和Set中的某些元素,当时使用边遍历,边删除的方法,却报了以下异常: ConcurrentModificationException 为了以后不忘记,使用烂笔头把它记录 ...

  9. spring post 图片

    @RequestMapping(value = "/post",method = RequestMethod.POST) @ResponseBody String GPost(@R ...

  10. JAVA中如何取得一个变量的类型

    class Test {public static void main(String[] args) {int i=1;System.out.println(getType(i));}public s ...