本文为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. Revit API修改链接文件房间边界

    start [Transaction(TransactionMode.Manual)] [Regeneration(RegenerationOption.Manual)] );//设置房间边界     ...

  2. .NET基于Eleasticsearch搭建日志系统实战演练

    一.需求背景介绍 1.1.需求描述 大家都知道C/S架构模式的客户端应用程序(比如:WinForm桌面应用.WPF.移动App应用程序.控制台应用程序.Windows服务等等)的日志记录都存储在本地客 ...

  3. 通过NTP协议进行时间同步

    最近发现手机的时间不是很准了,便到网上下了一个同步时间的小程序,简单了看了一下它的原理,是通过NTP协议来实现校时的,就顺便学习了一下NTP协议,用C#写了个简单的实现. NTP(Network Ti ...

  4. Windows Phone本地数据库(SQLCE):13、更新数据(翻译)

    这是“windows phone mango本地数据库(sqlce)”系列短片文章的第十三篇. 为了让你开始在Windows Phone Mango中使用数据库,这一系列短片文章将覆盖所有你需要知道的 ...

  5. Odoo9发行说明

    2015年10月1日,期待已久的Odoo9正式发布.本文是Odoo9正式版发行说明,基于官网资料翻译. 译者: 苏州-微尘原文地址:https://www.odoo.com/page/odoo-9-r ...

  6. The Topo to Raster tool returns errors 010235 and 010067转

    Problem: The Topo to Raster tool returns errors 010235 and 010067 Description The Topo to Raster geo ...

  7. OAuth2.0 原理流程及其单点登录和权限控制

    2018年07月26日 07:21:58 kefeng-wang 阅读数:5468更多 所属专栏: Java微服务构架   版权声明:[自由转载-非商用-非衍生-保持署名]-转载请标明作者和出处. h ...

  8. Java里多个Map的性能比较(TreeMap、HashMap、ConcurrentSkipListMap)

    比较Java原生的 3种Map的效率. 1.  TreeMap 2.  HashMap 3.  ConcurrentSkipListMap 模拟150W以内海量数据的插入和查找,通过增加和查找两方面的 ...

  9. Adapter数据变化改变现有View的实现原理及案例

    首先说说Adapter详细的类的继承关系.例如以下图 Adapte为接口它的实现类的对象作为AdapterView和View的桥梁,Adapter是装载了View(比方ListView和girdVie ...

  10. ntp测试

    cmd下 w32tm /stripchart /computer:time1.aliyun.com linux ntpdate ntp1.aliyun.com