Python的底層內(nèi)存模型之模塊、類、對象的存儲與運行機制
前言
這篇博客從內(nèi)存布局、對象存儲、屬性管理三個核心維度,總結(jié)匯總 Python 的底層內(nèi)存模型和運行機制
一、先編譯,后解釋
Python 既非純編譯型也非純解釋型語言,其運行流程可概括為:
源代碼(.py) → 編譯生成字節(jié)碼(.pyc) → Python虛擬機(PVM)解釋執(zhí)行字節(jié)碼 → 與操作系統(tǒng)交互
- 編譯階段:解釋器將源代碼轉(zhuǎn)為字節(jié)碼(中間代碼),并緩存到__pycache__目錄,重復(fù)運行時直接加載字節(jié)碼提升效率;
- 執(zhí)行階段:Python 虛擬機(PVM)逐行解釋字節(jié)碼,翻譯成機器指令執(zhí)行;
- 核心特性:CPython 的 GIL(全局解釋器鎖)限制同一時刻僅一個線程執(zhí)行字節(jié)碼,這也是 Python 多線程在 CPU 密集型任務(wù)中效率不高的核心原因。
Python 無 Java 式嚴格的 “堆、棧、方法區(qū)” 物理劃分,但從開發(fā)者視角可簡化為兩大核心區(qū)域:
| 區(qū)域 | 核心作用 | 存儲內(nèi)容 |
|---|---|---|
| 棧幀區(qū) | 臨時存儲函數(shù)調(diào)用上下文 | 局部變量、參數(shù)的引用(地址) |
| 堆區(qū) | 存儲所有實際數(shù)據(jù) | 所有對象(實例、類、模塊、函數(shù)等) |
二、模塊對象:.py 文件的 “屬性容器”
當我們導(dǎo)入模塊或運行.py文件時,Python 解釋器會為該文件創(chuàng)建一個模塊對象****(module 類型實例),這是模塊級內(nèi)容的核心載體。
- 模塊對象的核心特性
- 創(chuàng)建時機:import模塊或運行腳本時自動創(chuàng)建,創(chuàng)建后緩存到sys.modules(字典,key 為模塊名,value 為模塊對象的引用地址);
- 存儲內(nèi)容:模塊的__dict__屬性是其核心,等價于全局命名空間(globals()返回的就是該字典),包含:
- 自定義內(nèi)容:全局變量、類、函數(shù);
- 內(nèi)置屬性:file(文件路徑)、name(模塊名)等;
- 特殊場景:直接運行的腳本會被命名為__main__模塊,這也是if name == "main"的底層邏輯。
- __file__指向文件路徑
__file__并非代碼 “查找” 的結(jié)果,而是解釋器在創(chuàng)建模塊對象時,主動將文件路徑賦值給模塊對象的內(nèi)置屬性 —— 它是模塊對象的 “路徑標簽”,而非運行時動態(tài)查找的結(jié)果。
三、包的加載
- python在加載模塊時,會先加載模塊所在的包,當包第一次被導(dǎo)入時,Python 會執(zhí)行
__init__.py中的所有代碼,可以在這里做初始化操作(比如加載配置、初始化常量、檢查依賴等) - 當我們執(zhí)行 import my_package 或 from my_package import utils 時,Python 會按以下步驟把包 / 模塊加載成模塊對象(Module Object)
- 查找模塊 / 包的路徑,從sys.path中查找包
- 執(zhí)行其中的
__init__.py代碼,將該包內(nèi)的__init__.py模塊(python文件)構(gòu)建模塊對象,把__init__.py中定義的變量、導(dǎo)入的對象作為__init__.py模塊對象的屬性(__dict__字典中)
三、類對象與實例對象:屬性的分層存儲
類和實例對象是 Python 面向?qū)ο蟮暮诵?,二者的屬性存儲遵?“分層管理” 原則,核心載體仍是__dict__字典(堆區(qū)存儲)。
- 類對象:方法與類屬性的 “倉庫”
- 存儲邏輯:類對象(如class Person:定義的Person)作為模塊對象的屬性存在,其__dict__存儲:
- 類屬性(如species = “Human”);
- 方法(本質(zhì)是函數(shù)對象,如say_hello);
- 繼承特性:類屬性查找會逐層向上遍歷父類的__dict__(如Person繼承object,會查找object.dict)。
- 實例對象:獨有屬性的 “專屬空間”
- 存儲邏輯:實例(如p = Person())存在堆區(qū),每個實例有獨立的__dict__,僅存儲實例獨有屬性(如self.name);
- 屬性查找優(yōu)先級:實例訪問屬性時,先查自身__dict__ → 查類對象__dict__ → 查父類__dict__ → 拋出AttributeError;

- sys.module 是堆區(qū)的一塊緩沖區(qū),是個字典,存儲所有module對象,key是模塊名、value是module對象的引用地址
- 每一個module對象也是通過__dict__ 字典存儲著該模塊的所有全局變量、類對象、實例對象,key: 屬性名(類名、對象名、方法名),value:類、對象、方法的引用地址
- sys.modules 本身是堆區(qū)的字典對象,地址固定;類對象、實例對象、模塊對象的__dict__也是通過起始地址的固定偏移量計算出來的。
- 編譯完模塊文件后,先在堆區(qū)分配地址,創(chuàng)建存儲當前模塊的模塊對象,初始化其核心屬性(dict, file,name),然后將創(chuàng)建的當前模塊對象地址存儲到 sys.module 字典緩沖區(qū)中,然后解釋器會將當前模塊地址存儲到一個全局的 “模塊上下文” (模塊執(zhí)行幀,非棧幀),這個模塊上下文會貫穿程序執(zhí)行的始終,程序會實時從這個模塊執(zhí)行幀中拿到最近的模塊對象地址。
四、Python 內(nèi)存管理的核心原則
- 引用為王:Python 中所有變量賦值、屬性存儲都是 “引用傳遞”(存地址),而非 “值傳遞”(存數(shù)據(jù));
- 垃圾回收:堆區(qū)對象的生命周期由 “引用計數(shù)” 主導(dǎo)(計數(shù)為 0 則回收),分代回收補充處理循環(huán)引用;
- 分層查找:屬性訪問遵循 “實例→類→父類” 的優(yōu)先級,模塊對象的__dict__是全局命名空間的核心;
- 緩存優(yōu)化:小整數(shù)(-5~256)、短字符串等常駐 “只讀數(shù)據(jù)區(qū)”(堆區(qū)子集),全局共享避免重復(fù)創(chuàng)建。
五、總結(jié)
Python 的內(nèi)存模型可概括為 “兩區(qū)域、三對象、一核心”:
- 兩區(qū)域:棧幀區(qū)存引用,堆區(qū)存所有對象;
- 三對象:模塊對象管理文件級內(nèi)容,類對象管理方法和類屬性,實例對象管理獨有屬性;
- 一核心:所有對象的屬性都基于__dict__字典(或優(yōu)化數(shù)組)存儲,核心邏輯是 “引用 + 分層查找”。
到此這篇關(guān)于Python的底層內(nèi)存模型之模塊、類、對象的存儲與運行機制的文章就介紹到這了,更多相關(guān)python內(nèi)存模型存儲與運行機制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python調(diào)用百度api實現(xiàn)語音識別詳解
這篇文章主要介紹了Python通過調(diào)用百度api實現(xiàn)語音識別,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2021-12-12
Python深度學(xué)習(xí)albumentations數(shù)據(jù)增強庫
下面開始albumenations的正式介紹,在這里我強烈建議英語基礎(chǔ)還好的讀者去官方網(wǎng)站跟著教程一步步學(xué)習(xí),而這里的內(nèi)容主要是我自己的一個總結(jié)以及方便英語能力較弱的讀者學(xué)習(xí)2021-09-09
python高并發(fā)異步服務(wù)器核心庫forkcore使用方法
這篇文章主要介紹了python高并發(fā)異步服務(wù)器核心庫forkcore的使用方法,大家參考使用吧2013-11-11

