读Python源码(三)Python列表的表示

简介:

在家过了个春节快不知道自己是干啥的了:),今天收拾一下心情继续读一下python的源码。这一节打算探究一下Python中列表是如何实现的。

1.Python列表创建

首先来到listobject.c文件找到今天的主角PyListObject,像之前一样将它拆解开来。

typedef struct {
    PyObject ob_base;  // 在整数节已经介绍过,主要包含引用计数和类型
    Py_ssize_t ob_size;// 用于指明列表中包含几个元素
    PyObject **ob_item;
    Py_ssize_t allocated;
} PyListObject;

这样拆解之后我们会看到ob_item,allocated还不能很好的确定它们代表什么,那么我接着往下看列表是如何新建的,这里找到新建的方法PyList_New:

// 这里为了方便理解我把源码简化了一下
PyObject *
PyList_New(Py_ssize_t size)
{
    PyListObject *op;
    if (size < 0) {  // 检查列表元素个数不小于0
        PyErr_BadInternalCall();
        return NULL;
    }
    if (numfree) {  // 检查是否有缓存可用
        numfree--;
        op = free_list[numfree];
        _Py_NewReference((PyObject *)op);
    } else {
        op = PyObject_GC_New(PyListObject, &PyList_Type);
        if (op == NULL)
            return NULL;
    }
    // 下面就是开辟内存新建一个列表
    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();
        }
    }
    // 下面为ob_size和allocated赋初始值
    Py_SIZE(op) = size;
    op->allocated = size;
    _PyObject_GC_TRACK(op);
    return (PyObject *) op;
}

这样我们就可以看出allocated跟ob_size一致,ob_item指向列表内存空间。

2.Python列表填充元素

上面新建了列表元素全是NULL,接下来通过PyList_SetItem为列表填充值。

int PyList_SetItem(PyObject *op, Py_ssize_t i, PyObject *newitem)
{
    PyObject **p;
    if (!PyList_Check(op)) {  // 检查op类型
        Py_XDECREF(newitem);
        PyErr_BadInternalCall();
        return -1;
    }
    if (i < 0 || i >= Py_SIZE(op)) {  // 检查索引是否越界
        Py_XDECREF(newitem);
        PyErr_SetString(PyExc_IndexError,
                        "list assignment index out of range");
        return -1;
    }
    // 下面对指定元素赋值
    p = ((PyListObject *)op) -> ob_item + i;
    Py_XSETREF(*p, newitem);
    return 0;
}

设置完值必然还会有取值方法PyList_GetItem

PyObject *
PyList_GetItem(PyObject *op, Py_ssize_t i)
{
    if (!PyList_Check(op)) {
        PyErr_BadInternalCall();
        return NULL;
    }
    if (i < 0 || i >= Py_SIZE(op)) {
        if (indexerr == NULL) {
            indexerr = PyUnicode_FromString(
                "list index out of range");
            if (indexerr == NULL)
                return NULL;
        }
        PyErr_SetObject(PyExc_IndexError, indexerr);
        return NULL;
    }
    return ((PyListObject *)op) -> ob_item[i];
}

3.图示

下面就针对上述结构做一个简单的图示

从这里不难看出,其实这时候开辟的空间均只包含指针,也能理解了为什么Python中为什么列表是可变类型的。 

到这里先简单了解一下Python列表的创建,后面再一一查看对列表的操作。

 欢迎关注wx公众号:python web小栈,共同探讨学习

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值