zoukankan      html  css  js  c++  java
  • python list 底层数据结构是啥

    数组,不是链表(我没说错,是面试官搞错了).

    在Cpython 源码里面,如下所示:
    /Python/Include/cpython/listobject.h 有如下定义

    typedef struct {
        PyObject_VAR_HEAD
        /* Vector of pointers to list elements.  list[0] is ob_item[0], etc. */
        PyObject **ob_item;
    
        /* ob_item contains space for 'allocated' elements.  The number
         * currently in use is ob_size.
         * Invariants:
         *     0 <= ob_size <= allocated
         *     len(list) == ob_size
         *     ob_item == NULL implies ob_size == allocated == 0
         * list.sort() temporarily sets allocated to -1 to detect mutations.
         *
         * Items must normally not be NULL, except during construction when
         * the list is not yet visible outside the function that builds it.
         */
        Py_ssize_t allocated;
    } PyListObject;
    

    看注释 Vector of pointers to list elements. list[0] is ob_item[0], etc. 是个动态数组啊

    有关 list 的操作定义在 \Python\Objects\listobject.c 中,比如 append 操作

    int
    PyList_Append(PyObject *op, PyObject *newitem)
    {
        if (PyList_Check(op) && (newitem != NULL))
            return app1((PyListObject *)op, newitem);
        PyErr_BadInternalCall();
        return -1;
    }
    

    在来看 app1 函数

    static int
    app1(PyListObject *self, PyObject *v)
    {
        Py_ssize_t n = PyList_GET_SIZE(self);
    
        assert (v != NULL);
        assert((size_t)n + 1 < PY_SSIZE_T_MAX);
        if (list_resize(self, n+1) < 0)
            return -1;
    
        Py_INCREF(v);
        PyList_SET_ITEM(self, n, v);
        return 0;
    }
    

    再来看 list_resize

    static int
    list_resize(PyListObject *self, Py_ssize_t newsize)
    {
        PyObject **items;
        size_t new_allocated, num_allocated_bytes;
        Py_ssize_t allocated = self->allocated;
    
        /* Bypass realloc() when a previous overallocation is large enough
           to accommodate the newsize.  If the newsize falls lower than half
           the allocated size, then proceed with the realloc() to shrink the list.
        */
        if (allocated >= newsize && newsize >= (allocated >> 1)) {
            assert(self->ob_item != NULL || newsize == 0);
            Py_SET_SIZE(self, newsize);
            return 0;
        }
    
        /* This over-allocates proportional to the list size, making room
         * for additional growth.  The over-allocation is mild, but is
         * enough to give linear-time amortized behavior over a long
         * sequence of appends() in the presence of a poorly-performing
         * system realloc().
         * Add padding to make the allocated size multiple of 4.
         * The growth pattern is:  0, 4, 8, 16, 24, 32, 40, 52, 64, 76, ...
         * Note: new_allocated won't overflow because the largest possible value
         *       is PY_SSIZE_T_MAX * (9 / 8) + 6 which always fits in a size_t.
         */
        new_allocated = ((size_t)newsize + (newsize >> 3) + 6) & ~(size_t)3;
        /* Do not overallocate if the new size is closer to overallocated size
         * than to the old size.
         */
        if (newsize - Py_SIZE(self) > (Py_ssize_t)(new_allocated - newsize))
            new_allocated = ((size_t)newsize + 3) & ~(size_t)3;
    
        if (newsize == 0)
            new_allocated = 0;
        num_allocated_bytes = new_allocated * sizeof(PyObject *);
        items = (PyObject **)PyMem_Realloc(self->ob_item, num_allocated_bytes);
        if (items == NULL) {
            PyErr_NoMemory();
            return -1;
        }
        self->ob_item = items;
        Py_SET_SIZE(self, newsize);
        self->allocated = new_allocated;
        return 0;
    }
    

    可以看到数组进行了动态扩充(额,重新分配了空间)

    再看就要看PyMem_Realloc方法了,不过我的ide跳不到,不过我猜就是malloc然后复制

  • 相关阅读:
    【51nod1674】区间的价值 V2(算法效率--位运算合并优化+链表实现)
    【bzoj 2339】[HNOI2011]卡农(数论--排列组合+逆元+递推)
    关于中国剩余定理{附【转】中国剩余定理 }
    JavaScript操作BOM
    学员操作—统计考试平均成绩
    JavaScript基础
    JDBC
    进制
    事务
    复习
  • 原文地址:https://www.cnblogs.com/freesfu/p/15631858.html
Copyright © 2011-2022 走看看