Python篇--- Python 的加載、緩存、覆蓋機制

要理解?import?與?if __name__ == "__main__":?的關系,以及 Python 的加載、緩存、覆蓋機制,我們可以從 “模塊的兩種身份” 和 “導入的全過程” 入手,用通俗的例子一步步拆解。

一、核心:模塊的 “雙重身份” 與?__name__?的作用

每個?.py?文件(模塊)都有兩種可能的 “身份”:

  • 作為 “主程序” 直接運行(比如?python script.py);
  • 作為 “模塊” 被其他程序導入(比如?import script)。

__name__?這個內置變量就是用來區分這兩種身份的 “身份證”

  • 當模塊直接運行時,__name__?的值是?"__main__"
  • 當模塊被導入時,__name__?的值是模塊名(比如?script

而?if __name__ == "__main__":?就像一個 “身份檢查站”:只有當模塊是 “主程序” 時,才會執行縮進內的代碼(通常是程序的入口邏輯,比如?main()?函數)。

二、import?與?if __name__?的核心關系:導入時 “不執行主程序”

import?的作用是 “加載模塊并執行其頂層代碼”,但?if __name__ == "__main__":?塊內的代碼是 “主程序專屬邏輯”,導入時不會執行

我們用一個例子說清楚:

假設我們有兩個文件:

  • tool.py(工具模塊,可能被導入)
  • main.py(主程序,會導入?tool.py
1.?tool.py?的內容:
# tool.py
print("tool.py 的頂層代碼執行了")  # 頂層代碼(未縮進)def add(a, b):return a + b# 主程序邏輯:只有直接運行 tool.py 時才執行
if __name__ == "__main__":print("tool.py 被直接運行了(主程序模式)")print(add(1, 2))  # 輸出 3
2.?main.py?的內容(導入?tool.py):
# main.py
print("開始導入 tool.py...")
import tool  # 導入 tool 模塊
print("tool.py 導入完成")print(tool.add(3, 4))  # 使用 tool 中的函數
3. 兩種運行場景的對比:
  • 場景 1:直接運行?tool.py
    命令:python tool.py
    輸出:

    tool.py 的頂層代碼執行了
    tool.py 被直接運行了(主程序模式)
    3
    

    解釋:__name__?是?"__main__",所以?if?塊內的代碼被執行。

  • 場景 2:運行?main.py(導入?tool.py
    命令:python main.py
    輸出:

    開始導入 tool.py...
    tool.py 的頂層代碼執行了  # 導入時執行了 tool.py 的頂層代碼
    tool.py 導入完成
    7  # 成功使用 tool.add
    

    關鍵:導入?tool.py?時,只執行了它的頂層代碼print?和?add?函數定義),但?if __name__ == "__main__":?塊內的代碼沒有執行(因為此時?tool.py?的?__name__?是?"tool",不是?"__main__")。

總結關系
import?會觸發模塊的 “頂層代碼” 執行(定義函數、類、變量等),但?if __name__ == "__main__":?塊內的代碼是 “主程序專屬邏輯”,僅在模塊被直接運行時執行,導入時不執行。這確保了模塊被導入時,不會意外執行其 “主程序代碼”(比如測試邏輯、命令行交互等)。

三、加載機制:import?時模塊是如何被 “讀入” 的?

import?一個模塊的過程,就像 “找文件→讀內容→執行代碼→存起來” 的流程,具體分 4 步:

  1. 檢查緩存:先看這個模塊是否已經導入過(存在?sys.modules?字典中)。如果有,直接用緩存的模塊,不重復加載。
  2. 查找模塊:如果沒緩存,Python 會按?sys.path?列表中的路徑(當前目錄、標準庫目錄等)查找模塊文件(.py.pyc?等)。
  3. 加載并執行:找到文件后,Python 會讀取文件內容,執行其中的頂層代碼(定義函數、類、變量,以及未縮進的語句),并生成一個 “模塊對象”。
  4. 存入緩存:將生成的模塊對象存入?sys.modules,方便下次導入時直接使用。
加載機制與?if __name__?的互動:

在 “執行頂層代碼” 這一步,模塊中的所有未縮進代碼都會被執行(包括?import?其他模塊、定義函數等),但?if __name__ == "__main__":?塊內的代碼是否執行,取決于模塊的 “身份”:

  • 若模塊是被導入的(__name__ = 模塊名):if?條件不成立,塊內代碼不執行。
  • 若模塊是直接運行的(__name__ = "__main__"):if?條件成立,塊內代碼會被執行(屬于頂層代碼的一部分,只是被條件判斷包裹了)。

四、緩存機制:為什么模塊不會被重復加載?

Python 有一個 “模塊緩存”(sys.modules?字典),用來存儲已經導入的模塊對象。第一次導入模塊時會執行其代碼并緩存,后續導入直接用緩存,不會重復執行代碼

舉例說明:

# main.py
import sys
print("第一次導入 tool:")
import tool  # 第一次導入,執行 tool 的頂層代碼print("\n第二次導入 tool:")
import tool  # 第二次導入,直接用緩存,不執行代碼# 查看緩存中是否有 tool
print("\n緩存中是否有 tool?", "tool" in sys.modules)  # 輸出 True

運行?main.py?的輸出:

第一次導入 tool:
tool.py 的頂層代碼執行了  # 第一次導入時執行
第二次導入 tool:  # 第二次導入,無輸出(未執行代碼)
緩存中是否有 tool? True

緩存的意義

  • 提高效率:避免重復讀取文件和執行代碼,節省時間。
  • 保證一致性:多次導入的是同一個模塊對象,模塊內的全局變量狀態會被保留(比如計數器不會重置)。

五、覆蓋機制:命名沖突時誰會 “勝出”?

當導入的模塊 / 成員與當前作用域的變量、函數重名時,會發生 “覆蓋”(后定義的會覆蓋先定義的)。這與?import?的語法和執行順序有關。

1. 導入的成員覆蓋本地變量
# main.py
a = 10  # 本地變量 afrom tool import a  # 從 tool 導入 a(假設 tool.py 中 a=20)
print(a)  # 輸出 20(被導入的 a 覆蓋了本地 a)
2. 后導入的成員覆蓋先導入的
# main.py
from tool import add  # 假設 tool.add 是 a+bfrom other_tool import add  # other_tool.add 是 a*b(后導入)
print(add(2, 3))  # 輸出 6(被后導入的 add 覆蓋)
3. 模塊名覆蓋問題

如果你的腳本名與標準庫模塊名相同(比如?json.py),導入時會優先加載你的腳本,覆蓋標準庫模塊

# 假設你有一個 json.py 文件
# main.py
import json  # 會導入你的 json.py,而不是標準庫的 json

這會導致標準庫功能無法使用,所以不要用標準庫模塊名命名自己的腳本

六、總結

  1. import?與?__name__?的關系
    import?會執行模塊的頂層代碼,但?if __name__ == "__main__":?塊內的代碼僅在模塊直接運行時執行,導入時不執行,避免 “主程序邏輯” 被意外觸發。

  2. 加載機制
    導入模塊時,Python 會按 “查緩存→找文件→執行頂層代碼→存緩存” 的流程處理,__name__?決定主程序塊是否執行。

  3. 緩存機制
    模塊導入后會存入?sys.modules,后續導入直接用緩存,不重復執行代碼,保證效率和狀態一致性。

  4. 覆蓋機制
    命名沖突時,后定義 / 導入的對象會覆蓋先定義 / 導入的,需注意避免與標準庫或本地變量重名。

理解這些機制,能幫你更清晰地控制代碼的執行時機,避免導入時的意外行為(比如重復執行、命名沖突)。

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

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

相關文章

Java設計模式之行為型模式(訪問者模式)應用場景分析

訪問者模式(Visitor Pattern)作為Java設計模式中的“隱形冠軍”,常被開發者低估其價值。這一模式通過“雙分派”機制巧妙解耦數據結構與操作,為復雜系統的擴展提供了強大武器。在大廠項目中,訪問者模式往往出現在業務邏…

【IDEA】JavaWeb自定義servlet模板

方法一:(推薦去使用方法二,還能創建其它代碼模板)使用servlet模板創建Servlet類如果創建時找不到servlet模板:File -> Project Structure然后應用 -> OK,如果還是找不到Servlet模板,看看項…

Linux選擇

在內存中運行著的進程稱為( 服務 )。負責控制systemd系統和服務管理器的工具為( systemctl )命令。systemd管理系統服務的基本單位是( unit )。分配和管理資源的基本單位是( 進程 &#xf…

【Redis學習路|第一篇】初步認識Redis

概要: 深入探討NoSQL數據庫的核心特性,對比傳統關系型數據庫的差異,重點介紹Redis作為內存數據庫的優勢與應用場景。 文章目錄認識 NoSQLNoSQL vs SQL 對比1?? 結構化 vs 非結構化2?? 關聯 vs 非關聯3?? 查詢方式對比4?? 事務特性5?? 存儲方式…

java局域網聊天室小項目架構思路

java局域網聊天室小項目架構思路 項目需求 創建一個局域網聊天系統,要求:用戶在登錄界面登錄后進入聊天窗口界面,能實現多用戶同時在線聊天,并且用戶之間可以進行私聊 項目用到的技術棧 java網絡編程java多線程java面向對象編…

vulhub-corrosion2靶機

1.安裝靶機 https://download.vulnhub.com/corrosion/Corrosion2.ovahttps://download.vulnhub.com/corrosion/Corrosion2.ova 2.掃描IP 3.掃描端口 4.訪問端口 首先訪問一下80端口 訪問一個8080端口發現是一個apache的頁面 5.掃描目錄與漏洞探測 那么我們掃描一下目錄 80…

Mysql深入學習:慢sql執行

目錄 慢查詢日志 慢查詢主要步驟 11種慢查詢的場景分析 場景一:SQL 沒有建立索引 場景二:索引未生效的典型原因 場景三:LIMIT 深分頁導致性能下降 場景四:單表數據量過大導致 SQL 性能下降 場景五:ORDER BY 出現…

李宏毅深度學習教程 第8-9章 生成模型+擴散模型

【2025版】12 生成式對抗網絡GAN 一 – 基本概念介紹_嗶哩嗶哩_bilibili 目錄 1. GAN生成式對抗網絡 2. GAN的訓練 散度差異 3.WGAN 4.訓練GAN 5. 如何客觀評估GAN 6. 條件型生成(按照要求) 7. Cycle GAN(互轉配對) 8. d…

1.8 axios詳解

Axios的定義與核心特性Axios是一個基于Promise的現代化HTTP客戶端庫,主要用于在瀏覽器和Node.js 環境中發送HTTP請求,旨在簡化異步數據交互流程。其核心特性如下:跨平臺支持:在瀏覽器中通過XMLHttpRequest對象發送請求&#xff0c…

41.安卓逆向2-frida hook技術-過firda檢測(五)-利用ida分析app的so文件中frida檢測函數過檢測

免責聲明:內容僅供學習參考,請合法利用知識,禁止進行違法犯罪活動! 內容參考于:圖靈Python學院 工具下載: 鏈接:https://pan.baidu.com/s/1bb8NhJc9eTuLzQr39lF55Q?pwdzy89 提取碼&#xff1…

安卓調javaScript Not find method “forceLogout“ implementatidsignature or namesp

核對一下是否實現對應的javaScript或者javaScript的方法參數對不對, 在這里插入圖片描述我這里一開始實現了這個方法但是沒有給參數,一直報異常,后臺說token沒給就查token的問題,最后發現是搞偏了,兩個原因&#xff0c…

【Linux網絡】:UDP(傳輸層協議)

目錄 一、鋪墊知識 1、傳輸層 2、端口號 2.1、五元組表示 一個進程通信 2.2、端口號范圍劃分 2.3、知名端口 2.4、查看端口號 2.5、問題 3、pidof & netstat 命令 ①netsate 命令 ②pidof命令 二、UDP協議 1、UDP協議格式 2、UDP報文 1.1、UDP數據封裝的過…

Effective C++ 條款19: 設計class猶如設計type

Effective C 條款19:設計class猶如設計type核心思想:設計新的class時,應當像語言設計者設計內置類型一樣慎重,考慮對象的創建、銷毀、初始化、拷貝、類型轉換等所有方面。 ?? 1. 類設計的關鍵問題域 對象生命周期管理&#xff1…

《匯編語言:基于X86處理器》第11章 MS-Windows編程(3)

本章展示的是如何用32 位Microsoft Windows API進行控制臺窗口編程。應用編程接口(API:ApplicationProgramming Interface)是類型、常數和函數的集合體,它提供了一種用計算機代碼操作對象的方式。本章將討論文本I/O、顏色選擇、時間與日期、數據文件I/O,…

在 macOS 上通過 Docker 部署DM8 (ARM 架構)

概述 達夢數據庫 (DM8) 無法直接在 Apple macOS 操作系統上原生安裝,通常需要通過虛擬機(如 Parallels Desktop、VMware Fusion)進行部署。另一種更輕量級且受 macOS 支持的方案是利用 Docker 容器技術來構建開發與測試環境。本文檔將詳細介…

網絡協議之路由是怎么回事?

寫在前面 要想去外面的世界看看, 就離不了路由器,而路由器工作的原理就是路由,那么具體是怎么路由的呢?本文就一起來看下這部分內容。 1:路由的配置 配置一條路由無非就是在配置以下三個信息: 1:包要去哪里&#x…

2106. 摘水果,梳理思路

文章目錄題目概要java 解法詳解題目概要 在一個無限的 x 坐標軸上,有許多水果分布在其中某些位置。給你一個二維整數數組 fruits ,其中 fruits[i] [positioni, amounti] 表示共有 amounti 個水果放置在 positioni 上。fruits 已經按 positioni 升序排列…

深入理解消息隊列(MQ)核心原理與設計精髓

引言:從一個“不堪重負”的訂單系統說起想象一個簡化的電商下單流程:用戶點擊“下單”后,系統需要:在訂單數據庫中創建一條記錄。調用庫存服務,扣減商品庫存。調用營銷服務,給用戶發放積分和優惠券。調用通…

前端手撕題總結篇(算法篇——來自Leetcode牛客)

鏈表指定區域反轉 找到區間(頭和為 for循環當**時)->反轉鏈表(返回反轉過后的頭和尾)->連接 function reverseBetween( head , m , n ) {//preEnd&cur&nextStart cur.next斷開if(mn)return head;const vHeadNode…

從Excel到工時管理系統:企業如何選擇更高效的工時記錄工具?

還在為手工統計員工工時而頭疼嗎?月末堆積如山的Excel表格、反復核對的數據、層出不窮的差錯,這些問題正在拖慢企業的發展步伐。8Manage工時管理系統發現,傳統手工記錄不僅耗費大量人力,更讓寶貴的工時數據難以轉化為有效的管理決…