欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python整數(shù)對(duì)象實(shí)現(xiàn)原理詳解

 更新時(shí)間:2019年07月01日 10:44:10   作者:FOOFISH-PYTHON之禪  
這篇文章主要介紹了Python整數(shù)對(duì)象實(shí)現(xiàn)原理詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

整數(shù)對(duì)象在Python內(nèi)部用PyIntObject結(jié)構(gòu)體表示:

typedef struct {
PyObject_HEAD
long ob_ival;
} PyIntObject;

PyObject_HEAD宏中定義的兩個(gè)屬性分別是:

int ob_refcnt; 
struct _typeobject *ob_type;

這兩個(gè)屬性是所有Python對(duì)象固有的:

  • ob_refcnt:對(duì)象的引用計(jì)數(shù),與Python的內(nèi)存管理機(jī)制有關(guān),它實(shí)現(xiàn)了基于引用計(jì)數(shù)的垃圾收集機(jī)制
  • ob_type:用于描述Python對(duì)象的類(lèi)型信息。

由此看來(lái)PyIntObject就是一個(gè)對(duì)C語(yǔ)言中l(wèi)ong類(lèi)型的數(shù)值的擴(kuò)展,出于性能考慮,對(duì)于小整數(shù),Python使用小整數(shù)對(duì)象池small_ints緩存了[-5,257)之間的整數(shù),該范圍內(nèi)的整數(shù)在Python系統(tǒng)中是共享的。

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



而超過(guò)該范圍的整數(shù)即使值相同,但對(duì)象不一定是同一個(gè),如下所示:當(dāng)a與b的值都是10000,但并不是同一個(gè)對(duì)象,而值為1的時(shí)候,a和b屬于同一個(gè)對(duì)象。

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

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

struct _intblock {
struct _intblock *next;
PyIntObject objects[N_INTOBJECTS];
};
typedef struct _intblock PyIntBlock;
static PyIntBlock *block_list = NULL;
static PyIntObject *free_list = NULL;

這些內(nèi)存塊(PyIntBlock)通過(guò)一個(gè)單向鏈表組織在一起,表頭是block_list,表頭始終指向最新創(chuàng)建的PyIntBlock對(duì)象。

PyIntBlock有兩個(gè)屬性:next,objects。next指針指向下一個(gè)PyIntBlock對(duì)象,objects是一個(gè)PyIntObject數(shù)組(最終會(huì)轉(zhuǎn)變成單向鏈表),它是真正用于存儲(chǔ)被緩存的PyIntObjet對(duì)象的內(nèi)存空間。

free_list單向鏈表是所有PyIntBlock內(nèi)存塊中空閑的內(nèi)存。所有空閑內(nèi)存通過(guò)一個(gè)鏈表組織起來(lái)的好處就是在Python需要新的內(nèi)存來(lái)存儲(chǔ)新的PyIntObject對(duì)象時(shí),能夠通過(guò)free_list快速獲得所需的內(nèi)存。

創(chuàng)建一個(gè)整數(shù)對(duì)象時(shí),如果它在小整數(shù)范圍內(nèi),就直接從小整數(shù)緩沖池中直接返回,如果不在該范圍內(nèi),就開(kāi)辟一個(gè)大整數(shù)緩沖池內(nèi)存空間:

[intobject.c]
PyObject* PyInt_FromLong(long ival)
{
register PyIntObject *v; 
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
//[1] :嘗試使用小整數(shù)對(duì)象池
if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) {
v = small_ints[ival + NSMALLNEGINTS];
Py_INCREF(v);
return (PyObject *) v;
}
#endif
//[2] :為通用整數(shù)對(duì)象池申請(qǐng)新的內(nèi)存空間
if (free_list == NULL) {
if ((free_list = fill_free_list()) == NULL)
return NULL;
}
//[3] : (inline)內(nèi)聯(lián)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就是創(chuàng)建大整數(shù)緩沖池內(nèi)存空間的邏輯,該函數(shù)返回一個(gè)free_list鏈表,當(dāng)整數(shù)對(duì)象ival創(chuàng)建成功后,free_list表頭就指向了v->ob_type,ob_type不是所有Python對(duì)象中表示類(lèi)型信息的字段嗎?怎么在這里作為一個(gè)連接指針呢?這是Python在性能與代碼優(yōu)雅之間取中庸之道,對(duì)名稱(chēng)的濫用,放棄了對(duì)類(lèi)型安全的堅(jiān)持。把它理解成指向下一個(gè)PyIntObject的指針即可。

[intobject.c]
static PyIntObject* fill_free_list(void)
{
PyIntObject *p, *q;
// 申請(qǐng)大小為sizeof(PyIntBlock)的內(nèi)存空間
// block list始終指向最新創(chuàng)建的PyIntBlock
p = (PyIntObject *) PyMem_MALLOC(sizeof(PyIntBlock));
((PyIntBlock *)p)->next = block_list;
block_list = (PyIntBlock *)p;
//:將PyIntBlock中的PyIntObject數(shù)組(objects)轉(zhuǎn)變成單向鏈表
p = &((PyIntBlock *)p)->objects[0];
q = p + N_INTOBJECTS;
while (--q > p)
// ob_type指向下一個(gè)未被使用的PyIntObject。
q->ob_type = (struct _typeobject *)(q-1);
q->ob_type = NULL;
return p + N_INTOBJECTS - 1;
}

不同的PyIntBlock里面的空閑的內(nèi)存是怎樣連接起來(lái)構(gòu)成free_list的呢?這個(gè)秘密放在了整數(shù)對(duì)象垃圾回收的時(shí)候,在PyIntObject對(duì)象的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);
}

原來(lái)PyIntObject對(duì)象銷(xiāo)毀時(shí),它所占用的內(nèi)存并不會(huì)釋放,而是繼續(xù)被Python使用,進(jìn)而將free_list表頭指向了這個(gè)要被銷(xiāo)毀的對(duì)象上。

總結(jié)

  • Python中的int對(duì)象就是c語(yǔ)言中l(wèi)ong類(lèi)型數(shù)值的擴(kuò)展
  • 小整數(shù)對(duì)象[-5, 257]在python中是共享的
  • 整數(shù)對(duì)象都是從緩沖池中獲取的。
  • 整數(shù)對(duì)象回收時(shí),內(nèi)存并不會(huì)歸還給系統(tǒng),而是將其對(duì)象的ob_type指向free_list,供新創(chuàng)建的整數(shù)對(duì)象使用

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Python刪除指定字符之前或之后所有內(nèi)容的方法

    Python刪除指定字符之前或之后所有內(nèi)容的方法

    本文主要介紹了Python刪除指定字符之前或之后所有內(nèi)容的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • Python3中的bytes和str類(lèi)型詳解

    Python3中的bytes和str類(lèi)型詳解

    這篇文章主要介紹了Python3中的bytes和str類(lèi)型,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • Django封裝交互接口代碼

    Django封裝交互接口代碼

    這篇文章主要介紹了Django封裝交互接口代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-07-07
  • Python Numpy數(shù)組擴(kuò)展repeat和tile使用實(shí)例解析

    Python Numpy數(shù)組擴(kuò)展repeat和tile使用實(shí)例解析

    這篇文章主要介紹了Python Numpy數(shù)組擴(kuò)展repeat和tile使用實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • 代碼講解Python對(duì)Windows服務(wù)進(jìn)行監(jiān)控

    代碼講解Python對(duì)Windows服務(wù)進(jìn)行監(jiān)控

    本篇文章給大家分享了通過(guò)Python對(duì)Windows服務(wù)進(jìn)行監(jiān)控的實(shí)例代碼,對(duì)此有興趣的朋友可以學(xué)習(xí)參考下。
    2018-02-02
  • Python讀寫(xiě)Json涉及到中文的處理方法

    Python讀寫(xiě)Json涉及到中文的處理方法

    下面小編就為大家?guī)?lái)一篇Python讀寫(xiě)Json涉及到中文的處理方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-09-09
  • 基于Python實(shí)現(xiàn)層次性數(shù)據(jù)和閉包性質(zhì)

    基于Python實(shí)現(xiàn)層次性數(shù)據(jù)和閉包性質(zhì)

    這篇文章主要介紹了如何利用Python實(shí)現(xiàn)層次性數(shù)據(jù)和閉包性質(zhì),文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Python有一定幫助,需要的可以了解一下
    2022-05-05
  • Python中五種列表拷貝的方法

    Python中五種列表拷貝的方法

    這篇文章主要介紹了Python中五種列表拷貝的方法,在Python中,我們經(jīng)常會(huì)遇到需要拷貝列表的情形,下面針對(duì)常用的列表拷貝方法進(jìn)行介紹和總結(jié),希望可以給大家?guī)?lái)更多感性的認(rèn)識(shí)
    2022-02-02
  • Python提取支付寶和微信支付二維碼的示例代碼

    Python提取支付寶和微信支付二維碼的示例代碼

    本文將教你使用 Python 的圖像處理庫(kù) pillow,輕松批量提取圖片中間的方形二維碼部分。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-02-02
  • pytorch中retain_graph==True的作用說(shuō)明

    pytorch中retain_graph==True的作用說(shuō)明

    這篇文章主要介紹了pytorch中retain_graph==True的作用說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02

最新評(píng)論