python3 整數類型PyLongObject 和PyObject源碼分析

python3 整數類型PyLongObject 和PyObject源碼分析

一 測試環境介紹和準備

測試環境:

操作系統:windows10

Python版本:3.7.0 下載地址

VS版本:vs2015社區版(免費) 下載地址

win10SDK(安裝vs2015是可以選擇,如果沒有安裝則需要獨立安裝)

http://ffmpeg.club/python

二 如何查看源碼

1 下載python源碼

https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tar.xz

http://www.ffmpeg.club/python

下載後解壓縮

使用vs2015或者vs2017打開

Python-3.7.0\PCbuild\pcbuild.sln 解決方案文件

打開pythoncore項目可以找到\include\object.h文件

 

三 源碼分析

python源碼版本 python3.7.0

在python中所有的類型都可以轉爲PyObject類型,單python用的是c語言,並沒有繼承機制,我們可以通過源碼看它試如何實現的,我們先看PyObject源碼

1 PyObject 源碼

typedef struct _object {

_PyObject_HEAD_EXTRA

Py_ssize_t ob_refcnt;

struct _typeobject *ob_type;

} PyObject;

 

1-1 _PyObject_HEAD_EXTRA 源碼

我們先看第一個成員是一個宏 _PyObject_HEAD_EXTRA,這個宏是如下定義

#ifdef Py_TRACE_REFS

/* Define pointers to support a doubly-linked list of all live heap objects. */

#define _PyObject_HEAD_EXTRA \

struct _object *_ob_next; \

struct _object *_ob_prev;

 

#define _PyObject_EXTRA_INIT 0, 0,

 

#else

#define _PyObject_HEAD_EXTRA

#define _PyObject_EXTRA_INIT

#endif

 

通過代碼我們可以看出,它根據環境給_PyObject_HEAD_EXTRA設置的值有可能是空的,或者是一個雙向鏈表。通過編譯代碼我們知道,他在debug版本的python中是用的雙向鏈表,而在release版本中是空。

1-2 Py_ssize_t ob_refcnt 引用計數

Py_ssize_t 類型在32位程序中就是int,在64位win程序中是__int64

引用計數的策略後面我們專門寫文章分析

1-3 struct _typeobject *ob_type;

源碼比較長,就不全部列出來,這個結構體中包含了一個PyObject對象的所有相關操作函數和屬性,比如對象創建和銷燬函數,print對象的序列化函數等,存儲方式都是通過函數指針。所以每種python類型都會對各類操作函數指針做賦值設定。

其中的PyObject_VAR_HEAD宏內容如下

typedef struct {

PyObject ob_base;

Py_ssize_t ob_size; /* Number of items in variable part */

} PyVarObject;

 

 

2 PyLongObject 整數對象

 

digit

struct _longobject {

PyObject_VAR_HEAD

digit ob_digit[1];

};

2-1 小數預處理

對於比較小的數(-5到257 )直接返回初始化好的值,所以說大量的小整數時,不會新增額外的空間

do if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) { \

return get_small_int((sdigit)ival); \

} while(0)

 

2-2 按照數字的發小分配空間,以unsigned short爲單位

數字少於16位也就是2個字節的,用一個digit (unsigned short) 存放

數字少於32位也就是4個字節的,用兩個個digit (unsigned short) 存放

2-3 大數處理

如果是超大數,就用多個字節存放,由於變量就是一個 unsigned long,先看一下源碼:

對於不同的系統,大數能表示的範圍不一致,因爲數字採用的是unsigned long存放,在不同的系統大小不一致,可以見如下表

 

其中 windows 64位使用的是 LLP64所以 在window中python數字的最大值也就是4個字節,如果用它來存放64位指針的地址,就會丟失數據。

在linux(ubuntu16.04 64)使用的是LP64,,所以數字最大值就是8個字節。

相關視頻可以觀看

https://edu.csdn.net/course/detail/9701

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章