在 Python 中,模塊(module)是一級命名空間對象。無論是通過 import 加載的標準庫模塊、第三方模塊,還是直接運行的腳本本身,每個模塊都以對象形式存在于內存中,并通過其 __dict__ 屬性統一管理所有模塊級名稱。
理解模塊的 __dict__,不僅是掌握模塊工作機制的關鍵,也是深入理解 Python 命名空間模型、導入機制以及運行期動態行為的重要基礎。
一、模塊對象與模塊命名空間
(1)模塊是運行期對象,而非靜態概念
在 Python 中,模塊不是“代碼文件”的抽象概念,而是運行期存在的實際對象。
print(type(math)) #每一個模塊對象都擁有一組標準屬性,例如:
? __name__:模塊名稱
? __file__:模塊源文件路徑
? __spec__:模塊的導入規范
? __loader__:模塊加載器
? __dict__:模塊命名空間
其中,__dict__ 是模塊命名空間的唯一物理載體,存儲了模塊中的所有名稱。
(2)模塊 __dict__ 的定義
模塊 __dict__ 表示模塊級的命名空間本身。模塊中通過賦值語句、函數定義、類定義、import 語句創建的所有名稱,最終都存儲在這個字典中。
示例:
pass加載后查看其命名空間:
print(demo.__dict__.keys())輸出:
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__file__', '__cached__', '__builtins__', 'x', 'f', 'C'])可以看到,模塊 __dict__ 既包含用戶定義的變量、函數、類,也包含系統自動添加的元信息。
二、types 模塊與 ModuleType 的作用
為了準確理解模塊 __dict__,需要明確模塊對象的具體類型。
(1)types 模塊的角色
標準庫 模塊提供了對解釋器內部核心對象類型的標準化引用,如:
? FunctionType 函數類型
? MethodType 方法類型
? ModuleType 模塊類型
? GeneratorType 生成器類型
這些不是“新類型”,而是對既有內置類型的正式命名,便于類型檢查和明確意圖。
(2)ModuleType 的本質
types.ModuleType 表示模塊對象的類型:
print(type(math) is types.ModuleType) # True所有通過 import 得到的模塊對象,本質上都是 ModuleType 的實例。
(3)ModuleType 的構造語義
types.ModuleType(name, doc=None)參數含義:
? name:模塊名(對應 __name__)
? doc: 模塊文檔字符串(對應 __doc__)
示例:
print(m.__dict__) # {}(4)ModuleType 創建的是真實模塊對象
需要明確的一點是,types.ModuleType 創建的并不是“偽模塊”,而是真正的模塊對象。區別僅在于:
特性
import 創建的模塊
ModuleType 創建的模塊
代碼執行
自動執行模塊代碼
不自動執行代碼
__dict__ 填充
自動填充
初始為空字典
系統屬性
自動設置 __spec__、__loader__
需手動設置
注冊到 sys.modules
自動注冊
不自動注冊
在對象模型層面,它們完全一致:
print(type(m1) is type(m2)) # True(5)使用 ModuleType 的意義
使用 ModuleType 的目的在于:隔離模塊對象結構本身與 import 機制的副作用。
示例:
print(m.__dict__) # {'x': 42, 'hello': at ...>}這清晰地體現了:
? 模塊屬性 ≡ 模塊 .__dict__ 中的鍵值對
? 模塊命名空間完全由模塊 __dict__ 管理
三、模塊 __dict__ 的生命周期
模塊 __dict__ 的生命周期與模塊對象本身嚴格一致。
(1)創建階段
執行順序為:
1、創建模塊對象:實例化 ModuleType
2、初始化空 __dict__:創建空字典作為命名空間
3、執行模塊代碼:逐條執行語句,將結果寫入 __dict__。
exec(open('demo.py').read(), demo.__dict__) # 導入過程的“概念性等價描述”(2)運行階段:動態可變
模塊 __dict__ 是一個完全可寫的普通字典,可在運行時動態改變:
del demo.__dict__['new_var']模塊在運行期可以:
? 動態添加屬性/刪除屬性
? 可被反射、注入、修改
? 作為插件系統的載體
(3)銷毀階段
當模塊對象被垃圾回收時,模塊 __dict__ 隨對象一同銷毀,其命名空間不再存在。
通常,模塊會常駐內存,因為 sys.modules 持有對模塊對象的強引用。除非顯式從 sys.modules 中刪除,否則模塊對象及其 __dict__ 會一直存在。
四、模塊 __dict__ 與屬性訪問機制
模塊屬性訪問遵循簡單直接的規則:
module.attr在屬性存在的情況下,在語義上等價于:
module.__dict__['attr']二者在異常類型上略有差異。
屬性訪問特點:
? 無方法綁定:模塊中的函數始終是普通函數對象。
? 無 MRO 查找:不存在繼承鏈查找。
? 無描述符處理:不涉及 __get__/__set__ 協議,即使模塊中存在實現了描述符協議的對象,模塊屬性訪問也不會觸發描述符綁定邏輯。
? 直接字典查找:屬性訪問就是字典鍵查找。
示例:
demo.f() # 返回 "function",不會生成方法對象五、模塊 __dict__ 的典型用途
(1)反射與調試
可用于枚舉模塊成員、動態分析模塊結構以及 REPL / 調試器實現。
pdb.set_trace() # 調試器內部使用 __dict__ 訪問局部變量(2)動態注入 API
常見于插件系統、框架自動注冊以及運行期擴展接口。
sys.modules[module_name] = module(3)框架自動注冊
return decorator六、不同對象的命名空間對比
對象類型
__dict__ 特性
可變性
特殊行為
實例
普通 dict
完全可變
支持屬性訪問協議
mappingproxy
需通過賦值語句
支持繼承、描述符
模塊
普通 dict(完全可寫)
完全可變
直接字典映射
模塊是唯一一個頂層、全局、完全可變的命名空間對象,這也是它常被用作配置容器、插件載體、全局狀態管理的原因。
小結
模塊 __dict__ 是模塊命名空間的實體載體,保存了模塊中定義的全部名稱。模塊對象本質上是 types.ModuleType 的實例,其 __dict__ 是一個普通、完全可寫的字典。模塊加載時,解釋器創建模塊對象并逐步填充其 __dict__;運行期中,該字典可被動態修改。模塊屬性訪問直接映射到 __dict__ 查找,不涉及方法綁定或 MRO。
理解模塊 __dict__,是理解 Python 命名空間、import 機制以及動態特性的關鍵基礎。
![]()
“點贊有美意,贊賞是鼓勵”
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.