1. 程式人生 > >Python原始碼剖析----第二章

Python原始碼剖析----第二章

第二章  Python的整數物件

2.1 基本概念
在Python中,整數物件是不可變物件,即建立一個PyIntObject物件之後,就再也不能改變該物件所維護的那個真實的整數值了。但在實際Python的應用程式中,整數的使用太過廣泛,為避免頻繁建立,Python為整數物件使用了一個巧妙的緩衝池機制。事實上,幾乎python中所有的內建物件,都會有自己特有的物件池機制。

[intobject.h]
typedef struct{
 PyObject_HEAD #物件頭結構
 long ob_ival; #整數物件的值
} PyIntObject;
從定義中看出,Python中的整數物件PyIntObject實際上是對C中原生型別long的一個簡單包裝,而與整數物件PyIntObject相關的元資訊實際上都儲存在與其對應的型別物件PyInt_Type中:
[intobject.c]
PyTypeObject PyInt_Type= {
 PyObject_HEAD_INIT(&PyType_Type)
 0,
 "int",
 sizeof(PyIntObject),
 0,
 (destructor)int_dealloc, /*tp_dealloc, 整數物件的析構操作*/
 (printfunc)int_print, /*tp_print, 列印PyIntObject物件 */
 0,
 0,
 (cmpfunc)int_compare, /* tp_compare, 比較操作*/
 (reprfunc)int_repr,
 &int_as_number, /*tp_as_number, 數值操作集合, PyNumberMethods中包含39個函式指標對應39中可選操作 */
 0,
 0,
 (hashfunc)int_hash,/*tp_hash, 獲得Hash值*/
 0,
 (reprfunc)int_repr,/*tp_str,轉化成PyStringObject物件*/
 PyObject_GenericGetAttr,
 0,
 0,
 int_doc,
 0,
 0,
 0,
 0,
 0,
 0,
 int_methods, /*tp_methods, 成員函式集合 */
 0,
 0,
 0,
 0,
 0,
 0,
 0,
 0,
 0,
 int_new,
 (freefunc)int_free,/*tp_free, PyIntObject物件的釋放操作*/
);

2.2 Python中整數物件的系統結構

在實際的程式設計中,小數值的整數會被非常頻繁地使用,如果在系統堆上頻繁申請並釋放空間,不僅降低執行效率,而且會造成大量記憶體碎片,嚴重影響Python的整體效能,因此Python中,對小整數物件使用了物件池計數,通過巨集 [NSMALLEGINTS, NSMALLPOSINTS) 來確定小整數物件的定義區間,這些整數由Python直接將其對應的整數物件快取在記憶體中,並將指標存放在small_ints中。這個物件池的建立及初始化的過程在Python初始化的階段。

而對於大整數,由於空間限制,Python不可能將其完全快取,而是以PyIntBlock結構為基礎,通過兩個單向列表(PyIntBlock block_list, PyIntObject *free_list)來維護一塊記憶體空間由這些大整數輪流使用。

typedef struct _intblock{
	struct _intblock *next;
	PyIntObject objects[N_INTOBJECTS];
}PyIntBlock;
static PyIntBlock *block_list = NULL;
Static PyIntObject *free_list = NULL;
通過PyInt_FromLong可以考察到Python中一個整數物件PyIntObject的建立
PyObject *
PyInt_FromLong(long ival)
{
    register PyIntObject *v;
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
    if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) {
        v = small_ints[ival + NSMALLNEGINTS];
        Py_INCREF(v);
        return (PyObject *) v;
    }
#endif
    if (free_list == NULL) {
        if ((free_list = fill_free_list()) == NULL)
            return NULL;
    }
    /* Inline PyObject_New */
    v = free_list;
    free_list = (PyIntObject *)Py_TYPE(v);
    PyObject_INIT(v, &PyInt_Type);
    v->ob_ival = ival;
    return (PyObject *) v;
}
PyInt_FromLong會首先判斷小整數機制是否被啟用,如果確認小整數物件池被啟用且傳入的值屬於小整數範圍,則直接返回在池中對應的物件,否則,則轉向由block_list維護的通用物件池,從block中尋找一塊可用於儲存新的PyIntObject物件的記憶體, 如當前所有PyIntBlock中已經沒有空閒記憶體塊(freelist為空)時, Python將重新申請新的PyIntBlock並將其放入block_list, 而指標 *block_list會指向最新生成的block, 當Python需要銷燬某block中的一個整數物件時,會將該物件的使用計數置零,但其所佔用的記憶體並不會被歸還給系統,而是繼續有Python保留,並將其鏈入到free_list所維護的自由記憶體連結串列。

需要注意的是,通用物件池的大小並不是固定的,當一個整數物件的引用計數變為0時, 就會被Python回收,但是在int_dealloc中,僅僅是將該整數物件的記憶體重新加入到自由記憶體連結串列中,而不會將記憶體交回到系統堆。因此一旦系統堆中的某塊記憶體被Python申請用於整數物件,那麼這塊記憶體在Python結束前,永遠不會被釋放。因此從Python中對通用整數物件池的共享機制可以看出,Python用於實現物件池的記憶體與歷史上建立的整數物件的個數無關,而是與同一時刻共存的整數物件個數的最大值有關。

相關推薦

Python原始碼剖析----第二

第二章  Python的整數物件 2.1 基本概念 在Python中,整數物件是不可變物件,即建立一個PyIntObject物件之後,就再也不能改變該物件所維護的那個真實的整數值了。但在實際Python的應用程式中,整數的使用太過廣泛,為避免頻繁建立,Python為整數物件

Python原始碼剖析----第一

第一章 1.1 Python的內建物件 在python中,物件就是為C中的結構體在堆上申請的一塊記憶體,一般不能被靜態初始化 但是,型別物件是唯一的例外,python中所有的內建的型別物件都是被靜態初始化的。 Python中的內建物件的頭結構都是對Pyobject結構的擴充

Python學習系列-----第二 操作符與表達式

2.4 學習 -- alt ges 操作符 bsp nbsp images   2.1 數學運算和賦值的簡便方法     例如:        2.2 優先級     在python中運算符有優先級之分,高優先級的運算符先執行,低優先級的運算符後執行。下面是運算符優先級:(

路飛學城——python開發集訓——第二

決定 索引 ted 方法 插入 move 順序 其他 XP 一: 知識點總結 二進制轉換這些知識之前都有學過,暫且不記錄了。python2編碼用的是ASCII碼,python3用的則是utf-8,二者不兼容。 重點是python 的數據集,這個之前記錄過,就直接復制過來了

路飛學城——python開發集訓——第二(2)練習題

創建 用戶 oldboy second python pda 全部 input 列表 一: 本節學習心得與體會 體會到了編程就得,多練習,列表字典集合這些知識雖然簡單,但練習題做起來還是有點磕磕絆絆的。 加深了幾個重要的知識點的使用,譬如,在索引裏用索引names

路飛學城-python開發集訓-第二

values 增刪 val 拷貝 rom 保持 列表 利用 學習python 1.通過昨天聽必勝老師的講題客和alex老師的心靈雞湯,對個人發展和對學習的規劃有了一個清楚的認識,以後利用休息的時間多學習python,爭取實現自己的理想!2.知識點總結: 第二章學習了基本數據

Python學習(第二

img 開始 png 變量命名 spa cccccc otto pad 基本 一、 變量 1. type(變量名) 可以查看該變量的類型 2. 關於字符串的兩個運算符 + 與 * ,分別執行 拼接 和 重復 操作 3. 格式化輸出 %s 字符串 %d 整型 (%0

QCad原始碼分析 第二

       QCad中通過c++程式碼與js程式碼結合的方式開發,C++用於功能的開發,js用於邏輯的處理,啟用通過RScriptHandler類將c++類匯出為指令碼可呼叫的介面。 指令碼相關的類的關係如下圖:    

Python入門筆記—第二(分支迴圈 if,for,while)

第二章:分支迴圈 1.三大結構 順序(語句一條一條執行下去,則為順序,此處略過) 分支 迴圈 注:Python中沒有switch-case語句 2.分支—if 2.1 if   age = 19 if age > 19:

我要翻譯《Think Python》- 004 第二 變數, 表示式和語句

PDF原始檔地址 :  http://www.greenteapress.com/thinkpython/thinkpython.pdf [自述:這一章內容不多,但是由於時間關係,翻譯完成這一章也花了我一週的時間,跟我預想的進度相比已經落後了,得加油了,要不然翻譯完整本書就要到猴年馬月了。目前離翻譯完成

Python核心程式設計 第二--Network Programming

2.1 Introduction In this Section, we will take a brief look at network programming using sockets. But before we delve into that, w

Python 原始碼剖析(一)【python物件】

處於研究python記憶體釋放問題,在閱讀部分python原始碼,順便記錄下所得。 (基於《python原始碼剖析》(v2.4.1)與 python原始碼(v2.7.6)) 先列下總結:         python 中一切皆為物件,所以會先講明白pyth

Python原始碼剖析-Dict

為了刻畫某種關係,現代的程式語言都會提供關聯式的容器。關聯式容器中的元素分別是以(鍵(key)或值(value))這樣的形式存在。例如(3,5)(3,6)就是一對對應的鍵與值。 Python中的關聯式容器是PyDictObject。Python通過PyDictObject建

Python學習系列-----第二 操作符與表示式

  2.1 數學運算和賦值的簡便方法     例如:        2.2 優先順序     在python中運算子有優先順序之分,高優先順序的運算子先執行,低優先順序的運算子後執行。下面是運算子優先順序:(同一行的運算子具有相同的優先順序)        2.3 改變優先

Python 原始碼剖析》一些理解以及勘誤筆記(3)

以下是本人閱讀此書時理解的一些筆記,包含一些影響文義的筆誤修正,當然不一定正確,貼出來一起討論。 注:此書剖析的原始碼是2.5版本,在python.org 可以找到原始碼。紙質書閱讀,pdf 貼圖。 文章篇幅太長,故切分成3部分,這是第三部分。 p316: 初始化

Python原始碼剖析[1] —— 編譯Python

在中間的部分,可以看到Python的核心,直譯器(interpreter)。在直譯器中,箭頭的方向指示了Python執行時的資料流方向。其中Scanner對應詞法分析,將檔案輸入的Python原始碼或從命令列輸入的一行行Python程式碼切分為一個一個的token;Parser對應語法分析部分,在Scanne

Python原始碼剖析】物件模型概述

*Python* 是一門 **面向物件** 語言,實現了一個完整的面向物件體系,簡潔而優雅。 與其他面向物件程式語言相比, *Python* 有自己獨特的一面。 這讓很多開發人員在學習 *Python* 時,多少有些無所適從。 那麼,*P

Python編程從入門到實踐》第二_變量和簡單數據類型

數據類型 記錄 strip() 哪些 改變 解決方法 變量名 擔心 cal 什麽是變量呢? 舉例: >>> message = "Hello,Python!" >>> print (message) Hello,Python! 這

讀書筆記--《Python基礎教程第二版》-- 第五 條件、循環和其他語句

ja5.1 print和import的更多信息5.1.1 使用獨號輸出>>> print ‘Age:‘,42Age: 42>>> 1,2,3(1, 2, 3)>>> print 1,2,31 2 3>>> print (1,2,3)(1,

第二 Python基礎知識

固定 list 如何獲取 思路 加減乘除 方法 oat nal 既然 第1章 第一個Pyhton程序 Pyhton的兩種執行方式:交互式與腳本文件 1.1 交互式 l 交互式模式 直接在Windows或者Linux環境下打開Python解釋器執行。 優點: