python中的單下劃線“_”與雙下劃線“__”的使用場景及“左右雙下劃線”(魔術方法:`__xxx__`)

在Python中,單下劃線“_”和雙下劃線“__”的使用場景和含義有顯著區別,主要體現在命名約定語法

一、單下劃線“_”的使用場景

單下劃線更多是編程約定(而非強制語法),用于傳遞特定的“暗示”,不影響代碼的實際運行。

1. 作為臨時變量/占位符

用于表示“臨時”或“無關緊要”的變量,僅作為語法占位,無需實際使用。
示例

# 循環中不需要用到的變量
for _ in range(5):print("Hello")# 解包時忽略某些值(只關心第二個和第四個元素)
data = (10, 20, 30, 40)
_, b, _, d = data  # 用_忽略10和30
print(b, d)  # 輸出:20 40
2. 表示“內部使用”的變量/函數(模塊/類級別)

按約定,單下劃線開頭的變量、函數或類(如_x_func())表示“僅供內部使用”,不建議外部直接訪問(但Python不強制限制)。
示例

# 模塊內的“內部”變量
# mymodule.py
_x = 100  # 暗示外部不要直接使用def _internal_func():  # 內部工具函數return "內部邏輯"def public_func():  # 公開接口return _internal_func()  # 內部調用# 外部導入時,默認不會導入單下劃線開頭的對象
from mymodule import *  # 不會導入_x和_internal_func

在類中,單下劃線開頭的屬性/方法也表示“內部使用”,提醒子類或外部不要隨意修改:

class MyClass:def __init__(self):self.public = "公開屬性"self._internal = "內部屬性(約定)"  # 外部仍可訪問,但不建議def _internal_method(self):  # 內部方法return "內部邏輯"def public_method(self):return self._internal_method()  # 內部調用
3. 交互式解釋器中的“上一次結果”

在Python交互式環境(如IDLE、Jupyter)中,_會自動保存上一次表達式的結果。
示例

>>> 1 + 2
3
>>> _  # 引用上一次結果
3
>>> _ * 2
6
>>> _
6
4. 數字分隔符(Python 3.6+)

用于分割長數字,提高可讀性(不影響數值本身)。
示例

large_num = 1_000_000  # 等價于1000000
print(large_num)  # 輸出:1000000pi = 3_1415_9265  # 更易讀的格式

二、雙下劃線“__”的使用場景

雙下劃線有明確的語法特性,不僅是約定,會影響Python的解析行為。

1. 名稱修飾(Name Mangling):避免子類覆蓋父類成員

在類中,雙下劃線開頭的變量或方法(如__x)會被Python自動“修飾”(重命名),形式為_ClassName__x,防止子類意外覆蓋父類的成員。
原理:Python解釋器在編譯時會修改名稱,確保父類的私有成員在子類中不被沖突。
示例

class Parent:def __init__(self):self.__secret = "父類的秘密"  # 雙下劃線開頭def __print_secret(self):  # 雙下劃線開頭的方法print(self.__secret)class Child(Parent):def __init__(self):super().__init__()self.__secret = "子類的秘密"  # 看似重名,實際不會沖突def __print_secret(self):  # 看似重寫,實際不會覆蓋父類方法print(self.__secret)# 測試
p = Parent()
c = Child()# 直接訪問會報錯(因為名稱已被修飾)
# print(p.__secret)  # AttributeError# 查看修飾后的名稱
print(p._Parent__secret)  # 輸出:父類的秘密(正確訪問方式)
print(c._Child__secret)   # 輸出:子類的秘密(正確訪問方式)p._Parent__print_secret()  # 輸出:父類的秘密
c._Child__print_secret()   # 輸出:子類的秘密

注意:名稱修飾的目的不是“禁止訪問”,而是“避免意外覆蓋”。通過_ClassName__member仍可訪問(不建議)。

2. 雙下劃線開頭和結尾:魔術方法(Magic Methods)

格式為__xxx__的方法是Python的“魔術方法”(或“特殊方法”),由Python內置定義,用于實現類的特殊行為(如構造、比較、運算等)。
特點

  • 由Python自動調用(如__init__在創建對象時調用),無需手動調用。
  • 用戶不應自定義類似格式的方法(避免與內置功能沖突)。

示例

class MyClass:def __init__(self, value):  # 構造方法,創建對象時調用self.value = valuedef __str__(self):  # 定義print()時的輸出格式return f"MyClass(value={self.value})"def __add__(self, other):  # 定義+運算符的行為return MyClass(self.value + other.value)obj1 = MyClass(10)
obj2 = MyClass(20)
print(obj1)  # 自動調用__str__(),輸出:MyClass(value=10)
print(obj1 + obj2)  # 自動調用__add__(),輸出:MyClass(value=30)

三、魔術方法(Magic Methods,又稱特殊方法,格式為__xxx__

前面我們提到魔術方法(Magic Methods,又稱特殊方法,格式為__xxx__),這里我們詳細討論一下。
魔術方法是Python中預定義的特殊函數,用于讓自定義類實現與Python內置語法、函數或運算符的交互能力。它們的核心作用是“讓自定義對象像內置對象(如列表、字典、整數)一樣自然地融入Python生態”,大幅提升代碼的可讀性和易用性。

1、對象的創建與生命周期管理

用于控制對象的創建、初始化、銷毀等過程,是最基礎的魔術方法。

魔術方法作用應用場景舉例
__new__(cls)實例創建的第一步(分配內存),返回實例實現單例模式(確保類只有一個實例)
__init__(self)實例初始化(設置初始屬性)所有類的基礎初始化(必用)
__del__(self)實例被銷毀時調用(垃圾回收)釋放資源(如關閉文件、數據庫連接)

示例:單例模式(__new__
確保一個類只有一個實例(如配置管理器、日志管理器):

class Singleton:_instance = None  # 存儲唯一實例def __new__(cls):if cls._instance is None:cls._instance = super().__new__(cls)  # 首次創建實例return cls._instance  # 后續調用直接返回已有實例# 測試:無論創建多少次,都是同一個實例
a = Singleton()
b = Singleton()
print(a is b)  # 輸出:True
2、字符串表示與格式化

用于定義對象轉換為字符串的規則,影響print()str()repr()等函數的輸出,便于調試和用戶交互。

魔術方法作用區別
__str__(self)返回“用戶友好”的字符串表示str(obj)print(obj)調用
__repr__(self)返回“開發者友好”的字符串表示(可重現對象)repr(obj)、控制臺直接輸出調用

示例:自定義日志對象的字符串表示

class Log:def __init__(self, level, message):self.level = levelself.message = messagedef __str__(self):# 用戶看到的簡潔信息return f"[{self.level.upper()}] {self.message}"def __repr__(self):# 開發者看到的詳細信息(可用于重建對象)return f"Log(level='{self.level}', message='{self.message}')"log = Log("error", "文件不存在")
print(log)  # 調用__str__:[ERROR] 文件不存在
print(repr(log))  # 調用__repr__:Log(level='error', message='文件不存在')
3、運算符重載

讓自定義對象支持Python的內置運算符(如+==>等),使代碼更直觀。

魔術方法對應運算符/操作應用場景
__add__(self, other)self + other自定義加法(如向量相加、字符串拼接)
__sub__(self, other)self - other自定義減法
__eq__(self, other)self == other自定義相等性判斷
__lt__(self, other)self < other自定義小于比較(支持排序)
__len__(self)len(self)支持長度計算(如容器類)

示例:實現向量加法與比較

class Vector:def __init__(self, x, y):self.x = xself.y = y# 支持向量加法:v1 + v2def __add__(self, other):return Vector(self.x + other.x, self.y + other.y)# 支持相等判斷:v1 == v2def __eq__(self, other):return self.x == other.x and self.y == other.y# 支持小于判斷(按模長):v1 < v2def __lt__(self, other):return (self.x**2 + self.y**2) < (other.x**2 + other.y**2)def __str__(self):return f"Vector({self.x}, {self.y})"v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2)  # 調用__add__:Vector(4, 6)
print(v1 == v2)  # 調用__eq__:False
print(v1 < v2)   # 調用__lt__:True(v1模長√5 < v2模長√25)
4、容器行為模擬

讓自定義類像內置容器(列表、字典、集合)一樣支持索引、切片、迭代、in判斷等操作。

魔術方法對應操作應用場景
__getitem__(self, key)obj[key](獲取元素)支持索引/切片訪問(如自定義列表)
__setitem__(self, key, value)obj[key] = value(設置元素)支持賦值操作
__contains__(self, item)item in obj(成員判斷)支持in運算符
__iter__(self)迭代(for item in obj讓對象可迭代
__len__(self)len(obj)(長度)支持長度計算

示例:實現一個簡易的自定義列表

class MyList:def __init__(self, data):self.data = list(data)# 支持索引訪問:obj[i]def __getitem__(self, key):return self.data[key]# 支持賦值:obj[i] = valuedef __setitem__(self, key, value):self.data[key] = value# 支持in判斷:item in objdef __contains__(self, item):return item in self.data# 支持迭代:for item in objdef __iter__(self):return iter(self.data)  # 委托給內置列表的迭代器# 支持len():len(obj)def __len__(self):return len(self.data)ml = MyList([1, 2, 3, 4])
print(ml[1])  # 調用__getitem__:2
ml[2] = 100   # 調用__setitem__
print(3 in ml)  # 調用__contains__:False(已被改為100)
for item in ml:  # 調用__iter__print(item, end=" ")  # 輸出:1 2 100 4
5、上下文管理(with語句)

通過__enter____exit__實現“資源自動獲取與釋放”,無需手動處理關閉(如文件、數據庫連接)。

魔術方法作用
__enter__(self)進入with塊時調用,返回資源對象
__exit__(self, exc_type, exc_val, exc_tb)退出with塊時調用,釋放資源(無論是否出錯)

示例:自定義文件管理器(自動關閉文件)

class FileManager:def __init__(self, filename, mode):self.filename = filenameself.mode = modeself.file = Nonedef __enter__(self):self.file = open(self.filename, self.mode)  # 獲取資源return self.file  # 允許with ... as f使用def __exit__(self, exc_type, exc_val, exc_tb):self.file.close()  # 釋放資源(必執行)# 可處理異常(如返回True表示已處理異常)return False# 使用with語句:自動調用__enter__和__exit__
with FileManager("test.txt", "w") as f:f.write("Hello, Magic Methods!")
# 退出with塊后,文件已自動關閉,無需手動f.close()
6、屬性訪問控制

用于攔截或定制對象的屬性訪問(獲取、設置、刪除),實現動態屬性、權限控制等。

魔術方法作用應用場景
__getattr__(self, name)訪問不存在的屬性時調用動態生成屬性(如從字典映射)
__setattr__(self, name, value)設置屬性時調用(包括存在的)限制屬性修改(如只讀屬性)
__delattr__(self, name)刪除屬性時調用禁止刪除關鍵屬性

示例:動態映射屬性到內部字典

class DynamicAttr:def __init__(self):self.data = {"name": "默認名稱", "age": 0}  # 內部存儲# 訪問屬性時,從data中獲取(如obj.name → data["name"])def __getattr__(self, name):if name in self.data:return self.data[name]raise AttributeError(f"屬性'{name}'不存在")# 設置屬性時,存入data(如obj.age = 18 → data["age"] = 18)def __setattr__(self, name, value):if name == "data":  # 特殊處理內部的data屬性super().__setattr__(name, value)else:self.data[name] = value  # 其他屬性存入dataobj = DynamicAttr()
print(obj.name)  # 調用__getattr__:默認名稱
obj.age = 20     # 調用__setattr__
print(obj.age)   # 輸出:20
obj.gender = "男"  # 動態添加新屬性
print(obj.gender)  # 輸出:男
7、可調用對象

通過__call__方法讓類的實例像函數一樣被調用,實現“帶狀態的函數”。

示例:帶計數器的函數

class Counter:def __init__(self):self.count = 0  # 維護狀態# 實例被調用時執行(如obj())def __call__(self):self.count += 1return f"已調用{self.count}次"counter = Counter()
print(counter())  # 調用__call__:已調用1次
print(counter())  # 輸出:已調用2次
print(counter.count)  # 查看狀態:2

魔術方法的核心價值是讓自定義類“適配”Python的內置語法和功能,使代碼更符合Python的“風格”(簡潔、直觀)。

合理使用魔術方法能大幅提升自定義類的靈活性和易用性,但避免過度使用(如自定義的__xxx__可能與內置功能沖突)。

四、回顧

類型本質作用場景語法強制力
單下劃線_編程約定臨時變量、內部成員(提示)、數字分隔符、交互式解釋器結果無(僅約定)
雙下劃線__語法特性名稱修飾(避免子類覆蓋)、魔術方法(__xxx__,內置行為)有(解釋器處理)
使用建議
  1. 單下劃線:遵循“內部成員”約定,提醒自己和他人不要隨意外部訪問,但不阻止訪問。
  2. 雙下劃線:僅在需要“防止子類覆蓋父類關鍵成員”時使用,避免過度使用(會降低代碼可讀性)。
  3. 魔術方法:僅使用Python內置的__xxx__方法,不自定義類似格式的方法(如__myfunc__)。

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

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

相關文章

我們為什么需要時序數據庫?

引言在當今數據驅動的世界中&#xff0c;時間序列數據正以前所未有的速度增長。從物聯網設備傳感器、金融交易記錄到應用程序性能監控&#xff0c;時間序列數據無處不在。傳統的關系型數據庫在處理這類數據時往往力不從心&#xff0c;這時時序數據庫(Time Series Database, TSD…

python-林粒粒的視頻筆記1

python的方法和函數指什么 可變類型和不可變類型 不可變類型&#xff0c;比如字符串通過方法調用后&#xff0c;字符串本身的值不改變 要改變需要重新賦值才能進行改變 比如可變數據類型類型&#xff0c;調用方法后可以直接改變原列表 因此&#xff0c;可變數據類型需要再重新賦…

CentOS 7的下載與安裝

一 、CentOS 7的下載與安裝 注意&#xff1a; CentOS 7 已于2024年6月30日停止維護&#xff01; 1、下載 由于 centos 7 已經停止維護&#xff0c;部分鏡像網站移除了對centos 7的支持&#xff0c;這里找到了部分現在還可以使用的鏡像網站 阿里云開源鏡像站&#xff1a;http…

礦物分類系統開發筆記(二):模型訓練[刪除空缺行]

目錄 一、階段銜接與開發目標 二、數據準備 三、模型選擇與訓練 1. 邏輯回歸&#xff08;LR&#xff09; 2. 隨機森林&#xff08;RF&#xff09; 3. 高斯樸素貝葉斯&#xff08;GNB&#xff09; 4. 支持向量機&#xff08;SVM&#xff09; 5. AdaBoost 6. XGBoost 四…

通信方式:命名管道

一、命名管道 1. 命名管道的原理 有了匿名管道&#xff0c;理解命名管道就非常簡單了。 對于普通文件而言&#xff0c;兩個進程打開同一個文件&#xff0c;OS是不會將文件加載兩次的&#xff0c;這兩個進程都會指向同一個文件&#xff0c;那么&#xff0c;也就享有同一份 in…

如何將數據庫快速接入大模型實現智能問數,實現chatbi、dataagent,只需短短幾步,不需要配置工作流!

智能問數系統初始化操作流程 一、系統初始化與管理員賬號創建登錄與初始化提示&#xff1a;首次訪問系統登錄頁&#xff0c;若系統未初始化&#xff0c;會彈出 “系統未完成初始化&#xff0c;請初始化管理員賬號” 提示&#xff0c;點擊【去創建】。填寫管理員信息&#xff1a…

告別手寫文檔!Spring Boot API 文檔終極解決方案:SpringDoc OpenAPI

在前后端分離和微服務盛行的今天&#xff0c;API 文檔是團隊協作的“通用語言”。一份清晰、準確、實時同步的文檔&#xff0c;能極大提升開發和聯調效率。然而&#xff0c;手動編寫和維護 API 文檔&#xff08;如 Word、Markdown 或 Postman&#xff09;是一場永無止境的噩夢—…

N4200EX是一款全智能超聲波檢測儀產品簡析

N4200EX是一款全智能超聲波檢測儀&#xff0c;適用于石油、石化、天然氣、氣體生產等行業的壓力管路、閥門、設備的各種防爆場合氣體泄漏、真空泄漏、閥門內漏檢測。●本安防爆設計&#xff0c;防爆、防塵、防水、抗摔。●適應惡劣環境&#xff0c;可在-25℃超低溫環境檢測&…

NestJS @Inject 裝飾器入門教程

一、核心概念解析 1.1 依賴注入&#xff08;DI&#xff09;的本質 依賴注入是一種設計模式&#xff0c;通過 IoC&#xff08;控制反轉&#xff09;容器管理對象生命周期。在 NestJS 中&#xff0c;Injectable() 標記的類會被容器管理&#xff0c;而 Inject() 用于顯式指定依賴項…

網絡地址詳解

子網劃分詳解&#xff1a;從 IP 地址結構到實際應用 在計算機網絡中&#xff0c;子網劃分是一項關鍵的技術&#xff0c;它能幫助我們更高效地管理 IP 地址資源&#xff0c;優化網絡性能。要深入理解子網劃分&#xff0c;首先需要從 IP 地址的基本結構說起。 一、IPv4 地址的基…

吾日三省吾身 | 周反思 8.19

上周一覽總體來說&#xff0c;上個周是一個被項目驅使而險些喪失自主思考能力的危險階段。相比任何有機械化工作經驗的讀者都有類似的體驗&#xff0c;在手上打螺絲的無盡循環中&#xff0c;自己的腦子就會逐漸喪失對自身的感知以及自主思考的能力。而這個負循環一旦開始&#…

08.19總結

連通性 在無向圖中&#xff0c;若任意兩點間均存在路徑相連&#xff0c;則該圖稱為連通圖。 若刪除圖中任意一個頂點后&#xff0c;剩余圖仍保持連通性&#xff0c;則該圖為點雙連通圖。 若刪除圖中任意一條邊后&#xff0c;圖仍保持連通性&#xff0c;則該圖為邊雙連通圖。 在…

車e估牽頭正式啟動乘用車金融價值評估師編制

8月13日&#xff0c;汽車金融行業職業能力評價規范編制啟動工作會議在廣州圓滿落幕。本次會議由中國機械工業聯合會機械工業人才評價中心主辦&#xff0c;廣州穗圣信息科技有限公司&#xff08;車e估&#xff09;承辦。會議匯聚了眾多行業精英&#xff0c;包括中國機械工業聯合…

清空 github 倉庫的歷史提交記錄(創建新分支)

想在 現有倉庫中創建一個新分支 master&#xff0c;刪除原來的 main&#xff0c;然后把 master 重命名為 main&#xff0c;并且清空歷史。可以用下面一條完整的命令序列操作&#xff1a; # 1. 創建一個沒有歷史的新分支 master git checkout --orphan master# 2. 添加當前所有文…

使用B210在Linux下實時處理ETC專用短程通信數據(2)-CPU單核高速數據處理

在上一篇文章中&#xff0c;使用Octave初步驗證了ETC車聯數據的格式。然而&#xff0c;Octave無法實時處理20M的采樣帶寬。我們本節通過C語言&#xff0c;重寫 Octave程序&#xff0c;實現實時處理&#xff0c;涉及下面三個關鍵特點。 文章目錄1. 全靜態內存2. 使用環狀緩存3 無…

Spark 運行流程核心組件(二)任務調度

1、調度策略參數默認值說明spark.scheduler.modeFIFO調度策略&#xff08;FIFO/FAIR&#xff09;spark.locality.wait3s本地性降級等待時間spark.locality.wait.processspark.locality.waitPROCESS_LOCAL 等待時間spark.locality.wait.nodespark.locality.waitNODE_LOCAL 等待時…

Orbbec---setBoolProperty 快捷配置設備行為

在奧比中光&#xff08;Orbbec&#xff09;SDK&#xff08;通常稱為ob庫&#xff09;中&#xff0c;setBoolProperty函數是用于設置設備或傳感器的布爾類型屬性的核心接口。它主要用于開啟/關閉設備的某些功能或模式&#xff0c;是配置設備行為的重要方法。 函數原型與參數解析…

[OWASP]智能體應用安全保障指南

1.關鍵組件定義 KC1 生成式語言模型&#xff08;Generative Language Models&#xff09; KC1.1 大語言模型&#xff08;LLMs&#xff09;&#xff1a;作為代理的“大腦”&#xff0c;基于預訓練基礎模型&#xff08;如 GPT 系列、Claude、Llama、Gemini&#xff09;&#xff…

【Vivado TCL 教程】從零開始掌握 Xilinx Vivado TCL 腳本編程(三)

【Vivado TCL 教程】從零開始掌握 Xilinx Vivado TCL 腳本編程&#xff08;三&#xff09; 系列文章目錄 1、VMware Workstation Pro安裝指南&#xff1a;詳細步驟與配置選項說明 2、VMware 下 Ubuntu 操作系統下載與安裝指南 3、基于 Ubuntu 的 Linux 系統中 Vivado 2020.1 下…

AI與大數據驅動下的食堂采購系統源碼:供應鏈管理平臺的未來發展

在數字化浪潮不斷加速的今天&#xff0c;很多企業和機構都在追求一個目標&#xff1a;如何把“效率”與“成本”做到最佳平衡。對于學校、企事業單位的食堂來說&#xff0c;采購環節就是重中之重。往小了說&#xff0c;它關系到食堂員工的工作體驗&#xff1b;往大了說&#xf…