中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python中整數對象的原理是什么

發布時間:2021-06-24 17:35:36 來源:億速云 閱讀:178 作者:Leah 欄目:大數據

Python中整數對象的原理是什么,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

整數對象在Python內部用PyIntObject結構體表示:

typedef struct {
    PyObject_HEAD
    long ob_ival;
} PyIntObject;

PyObject_HEAD宏中定義的兩個屬性分別是:

int ob_refcnt;        
struct _typeobject *ob_type;

這兩個屬性是所有Python對象固有的:

  • ob_refcnt:對象的引用計數,與Python的內存管理機制有關,它實現了基于引用計數的垃圾收集機制

  • ob_type:用于描述Python對象的類型信息。

由此看來PyIntObject就是一個對C語言中long類型的數值的擴展,出于性能考慮,對于小整數,Python使用小整數對象池small_ints緩存了[-5,257)之間的整數,該范圍內的整數在Python系統中是共享的。

#define NSMALLPOSINTS           257
#define NSMALLNEGINTS           5
static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];

超過該范圍的整數即使值相同,但對象不一定是同一個,如下所示:a與b的值都是10000,但并不是同一個對象,值都是1是,他們屬于同一個對象。

>>> a = 10000
>>> b = 10000
>>> print a is b
False
>>> a = 1
>>> b = 1
>>> print a is b
True

對于超出了[-5, 257)之間的其他整數,Python同樣提供了專門的緩沖池,供這些所謂的大整數使用,避免每次使用的時候都要不斷的malloc分配內存帶來的效率損耗。這塊內存空間就是PyIntBlock

struct _intblock {

    struct _intblock *next;
    PyIntObject objects[N_INTOBJECTS];
};
typedef struct _intblock PyIntBlock;

static PyIntBlock *block_list = NULL;
static PyIntObject *free_list = NULL;

這些內存塊(blocks)由一個單向鏈表表示,表頭是block_listblock_list始終指向最新創建的PyIntBlock對象。next指針指向下一個PyIntBlock對象,objects是一個PyIntObject數組(最終會轉變成單向鏈表),它是真正用于存儲被緩存的PyIntObjet對象的內存空間。 free_list單向鏈表是所有block的objects中空閑的內存。所有空閑內存通過一個鏈表組織起來的好處就是在Python需要新的內存來存儲新的PyIntObject對象時,能夠通過free_list快速獲得所需的內存。

Python中整數對象的原理是什么

創建一個整數對象時,如果它在小整數范圍內,就直接從小整數緩沖池中直接返回,如果不在該范圍內,就開辟一個大整數緩沖池內存空間:

[intobject.c]
PyObject* PyInt_FromLong(long ival)
{
     register PyIntObject *v; 
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
     //[1] :嘗試使用小整數對象池
     if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) {
        v = small_ints[ival + NSMALLNEGINTS];
        Py_INCREF(v);
        return (PyObject *) v;
    }
#endif
    //[2] :為通用整數對象池申請新的內存空間
    if (free_list == NULL) {
        if ((free_list = fill_free_list()) == NULL)
            return NULL;
    }
    //[3] : (inline)內聯PyObject_New的行為
    v = free_list;
    free_list = (PyIntObject *)v->ob_type;
    PyObject_INIT(v, &PyInt_Type);
    v->ob_ival = ival;
    return (PyObject *) v;
}

fill_free_list就是創建大整數緩沖池內存空間的邏輯,該函數返回一個free_list鏈表,當整數對象ival創建成功后,free_list表頭就指向了v->ob_typeob_type不是所有Python對象中表示類型信息的字段嗎?怎么在這里作為一個連接指針呢?這是Python在性能與代碼優雅之間取中庸之道,對名稱的濫用,放棄了對類型安全的堅持。把它理解成指向下一個PyIntObject的指針即可。

[intobject.c]
static PyIntObject* fill_free_list(void)
{
    PyIntObject *p, *q;
    // 申請大小為sizeof(PyIntBlock)的內存空間,并鏈接到已有的block list中
    // block list使用指向最新創建的PyIntBlock
    p = (PyIntObject *) PyMem_MALLOC(sizeof(PyIntBlock));
    ((PyIntBlock *)p)->next = block_list;
    block_list = (PyIntBlock *)p;

    //:將PyIntBlock中的PyIntObject數組——objects——轉變成單向鏈表
    p = &((PyIntBlock *)p)->objects[0];
    q = p + N_INTOBJECTS;
    while (--q > p)
        // ob_type指向下一個未被使用的PyIntObject。
        q->ob_type = (struct _typeobject *)(q-1);
    q->ob_type = NULL;
    return p + N_INTOBJECTS - 1;
}

不同的PyIntBlock里面的空閑的內存是怎樣連接起來構成free_list的呢?這個秘密放在了整數對象垃圾回收的時候,在PyIntObject對象的tp_dealloc操作中可以看到:

[intobject.c]
static void int_dealloc(PyIntObject *v)
{
    if (PyInt_CheckExact(v)) {
        v->ob_type = (struct _typeobject *)free_list;
        free_list = v;
    }
    else
        v->ob_type->tp_free((PyObject *)v);
}

原來PyIntObject對象銷毀時,它所占用的內存并不會釋放,而是繼續被Python使用,進而將free_list表頭指向了這個要被銷毀的對象上。

總結
  • Python中的int對象就是c語言中long類型數值的擴展

  • 小整數對象[-5, 257]在python中是共享的

  • 整數對象都是從緩沖池中獲取的。

  • 整數對象回收時,內存并不會歸還給系統,而是將其對象的obtype指向freelist,供新創建的整數對象使用

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

大邑县| 南溪县| 通城县| 涪陵区| 边坝县| 常熟市| 交城县| 嘉峪关市| 玉溪市| 滨海县| 太仆寺旗| 八宿县| 陵川县| 黎川县| 申扎县| 河北省| 河南省| 西畴县| 桓仁| 天镇县| 灵璧县| 枝江市| 民勤县| 托克逊县| 平阳县| 满洲里市| 交城县| 榆社县| 正宁县| 甘洛县| 泌阳县| 宁陵县| 洛阳市| 云林县| 通海县| 郯城县| 介休市| 永春县| 安平县| 汝城县| 达尔|