python的__init__.py

在此之前先確認一個概念是否弄清

模塊命名空間

1. 目錄結構

假設你有以下結構:

testpkg/__init__.pyfool.pymaybe.py

內容如下:

fool.py

# testpkg/fool.py
class Fool:pass

maybe.py

# testpkg/maybe.py
class Maybe:pass

__init__.py

(先什么也不寫,空文件)


2. 只import子模塊,不動__init__.py

在外部寫測試代碼:

import testpkg.fool
import testpkg.maybeprint(hasattr(testpkg, 'Fool')) # False
print(hasattr(testpkg, 'Maybe')) # Falseprint(hasattr(testpkg.fool, 'Fool')) # True
print(hasattr(testpkg.maybe, 'Maybe')) # True

解釋:

  • testpkg.fool模塊的命名空間里有Fool(因為在fool.py里定義了)
  • testpkg.maybe模塊的命名空間里有Maybe
  • 但是testpkg(這個包)的命名空間里沒有FoolMaybe,因為沒把它們導入到包的頂層。

3. “模塊命名空間”到底是什么?

  • 每個py文件(模塊)加載后,Python會創建一個名字空間(實際是一個dict),存放所有在這個模塊里定義的名字。
  • 可以通過模塊名.__dict__看到它的命名空間。

例如:

import testpkg.fool
import testpkg.maybeprint(testpkg.fool.__dict__.keys())
print(testpkg.maybe.__dict__.keys())
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__file__', '__cached__', '__builtins__', 'Fool'])
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__file__', '__cached__', '__builtins__', 'Maybe'])

4. 只有import到包,名字才會出現在包的命名空間

如果你修改testpkg/__init__.py為:

from testpkg.fool import Fool
from testpkg.maybe import Maybe__all__ = ["Fool", "Maybe"]
  • import testpkg 的時候,實際上會執行 testpkg/__init__.py 里的代碼。
  • from testpkg.fool import Fool 這行代碼的作用是:
    testpkg.fool 這個模塊里的 Fool,導入到當前命名空間(也就是 testpkg 的命名空間)下。
  • 同理,from testpkg.maybe import MaybeMaybe 導入到 testpkg 命名空間下。

現在再測試:

import testpkgprint(hasattr(testpkg, 'Fool')) # True
print(hasattr(testpkg, 'Maybe')) # Trueprint(testpkg.__dict__.keys())
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__path__', '__file__', '__cached__', '__builtins__', 'fool', 'Fool', 'maybe', 'Maybe', '__all__'])

此時FooBar被“綁定”到了testpkg這個包的命名空間下。

補充個__all__講解

__all__ 是一個導出控制列表,是一個字符串列表。

當你這樣用的時候:

from testpkg import *

Python 會只導入 __all__ 里列出的名字

也就是說:

  • 如果 __init__.py 里有 __all__ = ['Fool', 'Maybe']
  • 那么 from testpkg import * 只會導入 FoolMaybe
  • 其他即使你在 __init__.py 里定義了,也不會隨 * 導出。

注意

  • __all__ 只影響 from ... import * 這種用法。
  • 普通的 import testpkg 不受影響。

非常好,你對模塊命名空間、以及 __init__.py 的作用已經理解得很清楚了!下面我會在你的基礎上,進一步系統性講解 __init__.py 文件,幫助你更深入理解它的地位與用法。


__init__.py 文件

一、__init__.py 的本質

  • __init__.py包的初始化腳本
  • 只要目錄下有 __init__.py,Python 才會把這個目錄當做一個(Python 3.3+ 以后支持“隱式命名空間包”,但強烈建議有 __init__.py,便于兼容和控制行為)。
  • 當你 import testpkg 時,Python 實際執行 testpkg/__init__.py,并把里面的內容放進 testpkg 這個模塊(包)對象的命名空間。

二、__init__.py 的作用

1. 標識包

  • 沒有 __init__.py,Python 2 不認這個目錄是包,會報錯。
  • Python 3.3+ 的確可以沒有(隱式包),但有了__init__.py能更清楚、兼容、可控。

2. 包初始化

  • 你可以在 __init__.py 里寫包初始化邏輯,比如設置全局變量、初始化狀態、打印調試信息等。

3. 控制包的“頂層接口”(API 設計

  • 你可以在 __init__.py 里導入(或重新命名)子模塊、類、函數,讓用戶用更簡單的方式訪問包內容。
  • 例如:
    # testpkg/__init__.py
    from .fool import Fool
    from .maybe import Maybe
    
    這樣用戶可以 from testpkg import Fool,不用知道子模塊結構。

4. 控制 from testpkg import * 導出的內容

  • 通過定義 __all__ 列表,決定哪些名字會被 * 導出。
    __all__ = ['Fool', 'Maybe']
    

5. 可以導入子包、子模塊

  • 你可以在 __init__.py 里導入子包、子模塊,甚至重命名,隱藏實現細節。
    from . import fool as _fool
    

三、實踐舉例

1. 最簡單的情況

# 空文件
  • 只起到“標識包”的作用。

2. 聚合包的接口(對外API)

# testpkg/__init__.py
from .fool import Fool
from .maybe import Maybe
__all__ = ['Fool', 'Maybe']
  • 這樣 testpkg.Fooltestpkg.Maybe 就變成包的“頂層接口”。

3. 初始化邏輯

# testpkg/__init__.py
print("testpkg包被導入了!")
_config = {"debug": True}
  • 導入包時會輸出一句話,設置包級別的配置。

4. 導出模塊而不是類

# testpkg/__init__.py
from . import fool
from . import maybe
__all__ = ['fool', 'maybe']
  • 這樣 from testpkg import fool 就可以直接用 testpkg.fool.Fool

四、幾點注意

  1. 相對導入和絕對導入

    • from .fool import Fool:點號代表“當前包”,推薦包內部用相對導入。
    • from testpkg.fool import Fool:絕對導入,避免循環依賴出錯。
  2. 循環引用問題

    • 包內部如果互相引用,要注意不要在模塊頂層出現死循環引用,否則會報 ImportError
  3. __init__.py 并不是必須的,但建議始終寫上

    • 這樣會讓代碼更清晰,有更好的兼容性。
  4. 包結構的“封裝”思路

    • 你可以只暴露有限的接口給用戶(通過__init__.py),隱藏實現細節。

五、你可以這樣理解

  • 包(package) = 文件夾 + __init__.py
  • 包的命名空間 = __init__.py 的命名空間
  • 你讓包有哪些“頂級名字”,就在 __init__.py 里加

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/86351.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/86351.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/86351.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

四核 A53+工業級存儲:移遠 SC200L 與 pSLC SD NAND 如何重構 T-BOX 性能邊界?

博客目錄 一、移遠 SC200L:T-BOX 的 “智慧大腦”二、米客方德 MKDN064GIL-ZA T-BOX:數據安全的堅固堡壘三、深度協同:拓展 T-BOX 應用邊界 在車聯網浪潮席卷而來的當下,T-BOX 作為汽車與外界交互的核心樞紐,其性能優劣…

JavaEE-統一功能處理

攔截器 實現強制登錄的功能, 后端程序根據Session來判斷??是否登錄, 但是實現?法是?較?煩的 需要修改每個接?的處理邏輯 需要修改每個接?的返回結果 接?定義修改, 前端代碼也需要跟著修改 有沒有更簡單的辦法, 統?攔截所有的請求, 并進?Session校驗呢, 這?我們學…

vscode運行c++文件和插件的方法

1.運行c文件全過程 VSCode運行C全教程-CSDN博客 按照以上的操作即可完成正常的配置流程。但是在運行我的文件時,總是出現終端和輸出混亂的情況,我想要在終端中進行輸入輸出的話,需要加一個改動:設置--輸入Run In Terminal--勾選…

利用云效實現自動化部署gitee倉庫中的項目

本文主要介紹如何利用云效 實現Node項目(vue/react....)自動化部署 1.準備工作 Git 倉庫【Gitee】 云服務器【華為云】 你的項目 2. 創建目錄 服務器上創建兩個目錄 一個專門用來放壓縮包: /home/www/dist (aaa.tgz bbb.tgz&am…

Flink SourceFunction深度解析:數據輸入的起點與奧秘

在Flink的數據處理流程中,StreamGraph構建起了作業執行的邏輯框架,而數據的源頭則始于SourceFunction。作為Flink數據輸入的關鍵組件,SourceFunction負責從外部數據源讀取數據,并將其轉換為Flink作業能夠處理的格式。深入理解Sour…

LabVIEW 共享變量通訊方式

在LabVIEW 開發中,共享變量(SharedVariable)作為實現數據實時交換的關鍵技術,廣泛應用于 LabVIEW、PLC 編程、分布式 SCADA 系統等領域。解析主流共享變量通訊機制的技術原理、性能特性及工程實踐中的選型策略。? 一、Network -P…

Angular進階之十二:Chrome DevTools+Angular實戰診斷指南

引言 最近有一個工單是說用戶在使用我們的系統的時候,如果使用某個頁面的次數多了以后瀏覽器就開始變慢甚至卡死崩潰掉。這個問題明顯是提示有內存泄露,今天就由這個問題開始分享一些關于內存泄漏的知識。 一、 Web 應用內存泄漏的危害與易忽略性 危害&…

在云服務器上搭建 MinIO 圖片存儲服務器及 Spring Boot 整合實現圖片上傳下載

一、MinIO 核心概念 MinIO 是一個高性能的分布式對象存儲服務器,兼容 Amazon S3 API,具有以下特點: 高性能:針對存儲和檢索優化 輕量級:單個二進制文件即可運行 云原生:支持 Kubernetes 部署 S3 兼容&a…

《深入解析:如何通過CSS集成WebGPU實現高級圖形效果》

當CSS的細膩筆觸遇上WebGPU的磅礴算力,兩者如同命運交織的織工,以代碼為絲線,在虛擬空間中編織出超越現實維度的靈境。這場融合不再局限于視覺呈現的革新,而是創造出一種能夠與用戶情感共鳴、突破物理法則束縛的沉浸式數字體驗&am…

R 語言科研繪圖 --- 環狀圖-匯總

在發表科研論文的過程中,科研繪圖是必不可少的,一張好看的圖形會是文章很大的加分項。 為了便于使用,本系列文章介紹的所有繪圖都已收錄到了 sciRplot 項目中,獲取方式: R 語言科研繪圖模板 --- sciRplothttps://mp.…

突破限制:實現頁面內精準監聽 localStorage 變更

突破限制:實現頁面內精準監聽 localStorage 變更 一、簡介二、示例演示三、StorageEvent重構setItem四、CustomEvent自定義事件同一頁面不同模塊數據同步五、MessageChannel同一頁面不同模塊數據同步六、BroadcastChannel多窗口數據同步七、CustomEventBroadcastCha…

牛客AI面試破解電銷招聘效率與成本雙重難題

在電銷行業,高流動性與大規模招聘需求長期困擾企業人力資源管理。傳統招聘模式下,HR需應對海量簡歷篩選、多輪面試協調、主觀評估偏差等挑戰,導致招聘周期長、成本高、人才匹配度低。如何通過技術手段實現精準篩選與效率提升?牛客…

智慧生產管控數字化平臺(源碼+文檔+講解+演示)

引言 在全球化和信息化的浪潮中,制造業正面臨著前所未有的挑戰和機遇。智慧生產管控數字化平臺應運而生,旨在通過數字化手段優化生產管控的全流程。本文將詳細介紹智慧生產管控數字化平臺的核心功能、技術架構以及如何通過開源代碼實現二次開發&#xf…

用Tensorflow進行線性回歸和邏輯回歸(九)

用TensorFlow訓練線性和邏輯回歸模型 這一節結合前面介紹的所有TensorFlow概念來訓練線性和邏輯回歸模型,使用玩具數據集。 用TensorFlow訓練模型 假如我們指明了數據點和標簽的容器,定義了張量操作的損失函數。添加了優化器節點到計算圖,…

使用 vue vxe-table 實現復選框禁用,根據行規則來禁用是否允許被勾選選中

使用 vue vxe-table 實現復選框禁用,根據行規則來禁用是否允許被勾選選中 查看官網:https://vxetable.cn 禁用選中 通過 checkMethod 方法控制 checkbox 是否允許用戶手動勾選,如果被禁用,可以調用 setCheckboxRow 方法手動設置…

【Linux-網絡】深入拆解TCP核心機制與UDP的無狀態設計

🎬 個人主頁:誰在夜里看海. 📖 個人專欄:《C系列》《Linux系列》《算法系列》 ?? 道阻且長,行則將至 目錄 📚引言 📚一、UDP協議 📖 1.概述 📖 2.特點 &#x1…

(nice!!!)(LeetCode 每日一題) 2081. k 鏡像數字的和 (枚舉)

題目:2081. k 鏡像數字的和 思路:枚舉10進制的回文串,然后來判斷對應的k進制數是否是回文串。直到有n個滿意即可。 而枚舉10進制的回文串,從基數p(1、10、100… )開始,長度為奇數的回文串,長度為偶數的回文…

Java面試題027:一文深入了解數據庫Redis(3)

Java面試題025:一文深入了解數據庫Redis(1) Java面試題026:一文深入了解數據庫Redis(2) 本節我們整理一下Redis高可用和消息隊列使用場景的重點原理,讓大家在面試或者實際工作中遇到這類問題時…

算法打卡 day4

4 . 高精度算法 性質:數組或者容器從低位往高位依次存儲大整數,方便進位。 4.1 高精度加法 給定兩個正整數(不含前導 0),計算它們的和。 輸入格式 共兩行,每行包含一個整數。 輸出格式 共一行,…

【筆記】Docker 配置阿里云鏡像加速(公共地址即開即用,無需手動創建實例)

2025年06月25日記 【好用但慎用】Windows 系統中將所有 WSL 發行版從 C 盤遷移到 非系統 盤的完整筆記(附 異常處理)-CSDN博客 【筆記】解決 WSL 遷移后 Docker 出現 “starting services: initializing Docker API Proxy: setting up docker ap” 問題…