最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

typedef struct {
PyObject_HEAD
long ob_ival;
} PyIntObject;

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

int ob_refcnt; 
struct _typeobject *ob_type;

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

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

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

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



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

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

對于超出了[-5, 257)之間的其他整數(shù),Python同樣提供了專門的緩沖池,供這些所謂的大整數(shù)使用,避免每次使用的時候都要不斷的malloc分配內(nè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)通過一個單向鏈表組織在一起,表頭是block_list,表頭始終指向最新創(chuàng)建的PyIntBlock對象。

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

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

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

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

[intobject.c]
static PyIntObject* fill_free_list(void)
{
PyIntObject *p, *q;
// 申請大小為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指向下一個未被使用的PyIntObject。
q->ob_type = (struct _typeobject *)(q-1);
q->ob_type = NULL;
return p + N_INTOBJECTS - 1;
}

不同的PyIntBlock里面的空閑的內(nèi)存是怎樣連接起來構(gòu)成free_list的呢?這個秘密放在了整數(shù)對象垃圾回收的時候,在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對象銷毀時,它所占用的內(nèi)存并不會釋放,而是繼續(xù)被Python使用,進而將free_list表頭指向了這個要被銷毀的對象上。

總結(jié)

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

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

相關(guān)文章

  • Python深度學(xué)習(xí)實戰(zhàn)PyQt5布局管理項目示例詳解

    Python深度學(xué)習(xí)實戰(zhàn)PyQt5布局管理項目示例詳解

    本文具體介紹基本的水平布局、垂直布局、柵格布局、表格布局和進階的嵌套布局和容器布局,最后通過案例帶小白創(chuàng)建一個有型的圖形布局窗口
    2021-10-10
  • vscode搭建之python?Django環(huán)境配置方式

    vscode搭建之python?Django環(huán)境配置方式

    這篇文章主要介紹了vscode搭建之python?Django環(huán)境配置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • 利用Python實現(xiàn)最小二乘法與梯度下降算法

    利用Python實現(xiàn)最小二乘法與梯度下降算法

    這篇文章主要介紹了利用Python實現(xiàn)最小二乘法與梯度下降算法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • Python import導(dǎo)入上級目錄文件的方法

    Python import導(dǎo)入上級目錄文件的方法

    這篇文章主要介紹了Python import導(dǎo)入上級目錄文件,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-01-01
  • Python+seaborn實現(xiàn)聯(lián)合分布圖的繪制

    Python+seaborn實現(xiàn)聯(lián)合分布圖的繪制

    聯(lián)合分布(Joint Distribution)圖是一種查看兩個或兩個以上變量之間兩兩相互關(guān)系的可視化圖,在數(shù)據(jù)分析操作中經(jīng)常需要用到。本文將通過seaborn實現(xiàn)繪制聯(lián)合分布圖,需要的可以參考一下
    2023-02-02
  • python接口自動化如何封裝獲取常量的類

    python接口自動化如何封裝獲取常量的類

    這篇文章主要介紹了python接口自動化如何封裝獲取常量的類,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12
  • 五分鐘學(xué)會Python 模塊和包、文件

    五分鐘學(xué)會Python 模塊和包、文件

    通過學(xué)習(xí)本文可以五分鐘掌握Python 模塊和包、文件的相關(guān)知識,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-08-08
  • Python如何提取html中文本到txt

    Python如何提取html中文本到txt

    這篇文章主要介紹了Python如何提取html中文本到txt問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • Python optparse模塊及簡單使用

    Python optparse模塊及簡單使用

    optparse,是一個更夠讓程序設(shè)計人員輕松設(shè)計出簡單明了、易于使用、符合標(biāo)準(zhǔn)的Unix命令例程式的Python模塊,生成使用和幫助信息,這篇文章主要介紹了Python optparse模塊簡單使用,需要的朋友可以參考下
    2022-12-12
  • Python中初始化一個二維數(shù)組及注意事項說明

    Python中初始化一個二維數(shù)組及注意事項說明

    這篇文章主要介紹了Python中初始化一個二維數(shù)組及注意事項說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08

最新評論

永嘉县| 东安县| 洛阳市| 镇赉县| 文水县| 台中县| 潜山县| 饶河县| 龙海市| 上思县| 高州市| 铜陵市| 青阳县| 东至县| 温州市| 五河县| 金门县| 云霄县| 新安县| 涿鹿县| 泽普县| 奎屯市| 乌兰浩特市| 府谷县| 德江县| 张掖市| 镶黄旗| 台中市| 大姚县| 沙湾县| 英德市| 镇远县| 弋阳县| 江都市| 台南市| 柳州市| 蒙阴县| 固镇县| 渭南市| 柳河县| 南丹县|