cpython: 列表對象的三種形態

cpyhton list 三種對象類型

  • PyList_Type
  • PyListIter_Type
  • PyListRevIter_Type

解釋器相關:

  • _PyList_Fini: 釋放解釋器中list緩存池,加速分配。
// PyInterpreterState
struct _Py_list_state list;
define PyList_MAXFREELIST 80

struct _Py_list_state {
    PyListObject *free_list[PyList_MAXFREELIST];
    int numfree;
};

UML:

相關文件:

  • cpython/Objects/listobject.c
  • cpython/Objects/clinic/listobject.c.h
  • cpython/Include/listobject.h
  • cpython/Objects/listsort.txt

2.0 List

list對象相關api.

  • PyList_Type
  • list_length: O(1)獲取列表長度
  • list_contains: O(n) 判定是否包含
  • list_extend: 觸發列表擴容.resize 增大
  • list_pop_impl: 觸發列表收縮.resize 減小
  • list_slice: 切片
  • PyList_GetSlice
    • list_slice
  • list_ass_slice
    • list_slice
  • list_copy_impl
    • list_slice

部分函數源碼分析:

static Py_ssize_t
list_length(PyListObject *a)
{
    /* O(1) 獲取可變對象頭中.ob_size*/
    return Py_SIZE(a);
}

static int
list_contains(PyListObject *a, PyObject *el)
{
    PyObject *item;
    Py_ssize_t i;
    int cmp;
    /* O(n) 變量比較 */
    for (i = 0, cmp = 0 ; cmp == 0 && i < Py_SIZE(a); ++i) {
        item = PyList_GET_ITEM(a, i);
        Py_INCREF(item);
        cmp = PyObject_RichCompareBool(item, el, Py_EQ);
        Py_DECREF(item);
    }
    return cmp;
}
static PyObject *
list_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
{
    PyListObject *np;
    PyObject **src, **dest;
    Py_ssize_t i, len;
    // 1.先計數新的切片後list對象的長度(size, ob_item指針的空間), 然後分配新的list對象np
    len = ihigh - ilow;
    np = (PyListObject *) list_new_prealloc(len);
    if (np == NULL)
        return NULL;

    src = a->ob_item + ilow;
    dest = np->ob_item;
    // 2.copy 源list對象的ob_item到新的list對象np的ob_item, 增加引用計數
    // copy的是列表中元素PyObject對象的指針. O(n)
    for (i = 0; i < len; i++) {
        PyObject *v = src[i];
        Py_INCREF(v);
        dest[i] = v;
    }
    Py_SET_SIZE(np, len);
    return (PyObject *)np;
}

2.1 List Iterator

  • PyListIter_Type
  • listiter_*

迭代器協議

__iter__: self
__next__:

eg: listiter_next 實現

static PyObject *
listiter_next(listiterobject *it)
{
    PyListObject *seq;
    PyObject *item;

    assert(it != NULL);
    // 1.獲取當前list對象
    seq = it->it_seq;
    if (seq == NULL)
        return NULL;
    assert(PyList_Check(seq));

    if (it->it_index < PyList_GET_SIZE(seq)) {
        // 2.獲取索引標記位置的對象, 索引位置++. 正向遍歷
        item = PyList_GET_ITEM(seq, it->it_index);
        ++it->it_index;
        Py_INCREF(item);
        return item;
    }

    it->it_seq = NULL;
    Py_DECREF(seq);
    return NULL;
}

2.2 List Reverse Iterator

  • PyListRevIter_Type
  • listreviter_*

eg: listiter_next 實現

static PyObject *
listreviter_next(listreviterobject *it)
{
    PyObject *item;
    Py_ssize_t index;
    PyListObject *seq;

    assert(it != NULL);
    // 1.取出當前list對象
    seq = it->it_seq;
    if (seq == NULL) {
        return NULL;
    }
    assert(PyList_Check(seq));
    index = it->it_index;
    if (index>=0 && index < PyList_GET_SIZE(seq)) {
        item = PyList_GET_ITEM(seq, index);
        // 2.取出索引位置的對象,索引位置--(反向遍歷)
        it->it_index--;
        Py_INCREF(item);
        return item;
    }
    it->it_index = -1;
    it->it_seq = NULL;
    Py_DECREF(seq);
    return NULL;
}

3. list -> iter -> Reverse iter

>>>d = [1, 2, 3]   # 創建了d, d是一個列表對象
>>>[i for i in d]  # 此時,觸發d有列表對象生成listiterobject, 在for..in指令的上下文中
>>> c = d.__reversed__() # list => list_reverseiterator
>>> c              # c 是反向的迭代器. it_index = 2, next 調用時,it_index --
<list_reverseiterator object at 0x105baf3d0>    
>>> 

4.列表的排序算法:timsort

列表對象排序. timsort是工業級算法,其混用插入排序與歸併排序,二分搜索等算法, 亮點是充分利用待排序數據可能部分有序的事實, 並且依據待排序數據內容動態改變排序策略——選擇性進行歸併以及galloping。

  • timesort(todo):
    • 插入排序
    • 二分查找
    • 歸併排序:(非兩個兩個歸併, 在a中找到第一個大於b[0]的位置ai, a0,ai-1,b[0], ...)
  • gallop_left
  • gallop_right
  • count_run
  • binarysort
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章