一文詳解Python中的單下劃線(xiàn)_?、雙下劃線(xiàn)__
很多人從Go/Java轉(zhuǎn)Python的同學(xué)會(huì)疑惑
為什么python類(lèi)的默認(rèn)構(gòu)造函數(shù)是 init? 不是__init 不是init__ 或者_(dá)init_ ?
其實(shí)是因?yàn)閜ython的語(yǔ)法導(dǎo)致的。Python 里面沒(méi)有pubcli private,甚至默認(rèn)所有的類(lèi)的屬性都是公開(kāi)的。讓我們回想一下 **Python 的“訪(fǎng)問(wèn)控制”哲學(xué): “We are all consenting adults.”(我們都是有共識(shí)的成年人)。
Python 不強(qiáng)制限制你訪(fǎng)問(wèn)任何屬性或方法,而是相信開(kāi)發(fā)者知道自己在做什么。
| 特性 | Java / C++ | Python |
|---|---|---|
public | 顯式聲明 | 默認(rèn)就是公開(kāi)的 |
private | 編譯器強(qiáng)制禁止外部訪(fǎng)問(wèn) | 沒(méi)有真正的私有,只有約定 |
| 封裝性 | 通過(guò)訪(fǎng)問(wèn)修飾符強(qiáng)制實(shí)現(xiàn) | 通過(guò)命名約定 + 文檔 + 信任實(shí)現(xiàn) |
單下劃線(xiàn)_ 、雙下劃線(xiàn)__ 開(kāi)頭或者結(jié)尾的區(qū)別
開(kāi)頭/結(jié)尾的命名具有不同的語(yǔ)義和用途。它們不是語(yǔ)法強(qiáng)制的訪(fǎng)問(wèn)控制,而是約定(convention)或語(yǔ)言機(jī)制(如名稱(chēng)改寫(xiě)、特殊方法)
| 命名形式 | 是否特殊處理 | 用途說(shuō)明 | 能否外部訪(fǎng)問(wèn) | 建議 | 外部使用代碼示例 |
|---|---|---|---|---|---|
_xxx | ? 否 | 內(nèi)部實(shí)現(xiàn)(約定) | ? 能 | 用作“受保護(hù)”成員 | print(a._xxx) |
__xxx | ? 是(改名) | 避免子類(lèi)命名沖突 | ? 能(改名后) | 用于需隔離的內(nèi)部屬性 | print(a._A__xxx) |
_xxx_ | ? 否 | 無(wú)特殊含義 | ? 能 | 避免使用 | print(a._xxx_) |
__xxx__ | ? 是 | 魔術(shù)方法(語(yǔ)言保留) | ? 能 | 只用于標(biāo)準(zhǔn)魔術(shù)方法 | print(a.__xxx__()) |
在 Python 中,以單下劃線(xiàn) _ 或雙下劃線(xiàn) __ 開(kāi)頭/結(jié)尾的命名具有不同的語(yǔ)義和用途。它們不是語(yǔ)法強(qiáng)制的訪(fǎng)問(wèn)控制,而是約定(convention)或語(yǔ)言機(jī)制(如名稱(chēng)改寫(xiě)、特殊方法)。下面詳細(xì)解釋四種常見(jiàn)形式的區(qū)別:
1._xxx——“內(nèi)部使用”約定(Protected by convention)
含義:
- 表示這是一個(gè)內(nèi)部實(shí)現(xiàn)細(xì)節(jié),不應(yīng)被外部代碼直接依賴(lài)。
- 是一種軟性提示,不是強(qiáng)制限制。
特點(diǎn):
- 可以正常訪(fǎng)問(wèn):
obj._xxx? - 不會(huì)被
from module import *導(dǎo)入(模塊級(jí)別) - 常用于“受保護(hù)”的屬性或方法(類(lèi)似其他語(yǔ)言的
protected)
示例:
class MyClass:
def __init__(self):
self._internal = 42
obj = MyClass()
print(obj._internal) # 完全合法,但“不推薦”直接用
?? 用途:告訴其他開(kāi)發(fā)者:“這是我的私有實(shí)現(xiàn),未來(lái)可能變動(dòng),請(qǐng)別依賴(lài)它。”
2.__xxx——名稱(chēng)改寫(xiě)(Name Mangling)
含義:
- Python 自動(dòng)重命名該屬性,避免子類(lèi)意外覆蓋父類(lèi)同名屬性。
- 不是為了隱私或安全,而是解決命名沖突。
特點(diǎn):
- 在類(lèi)
MyClass中定義__private,實(shí)際存儲(chǔ)為_MyClass__private - 仍可從外部訪(fǎng)問(wèn):
obj._MyClass__private? - 僅在類(lèi)定義內(nèi)生效(必須出現(xiàn)在類(lèi)作用域中)
示例:
class Parent:
def __init__(self):
self.__secret = "parent"
class Child(Parent):
def __init__(self):
super().__init__()
self.__secret = "child" # 不會(huì)覆蓋父類(lèi)的 __secret!
c = Child()
print(c._Parent__secret) # 輸出: parent
print(c._Child__secret) # 輸出: child
?? 用途:防止子類(lèi)“不小心”覆蓋父類(lèi)的內(nèi)部屬性。
3._xxx_——通常無(wú)特殊含義(但建議避免)
含義:
- 前后各一個(gè)下劃線(xiàn),Python 不會(huì)對(duì)此做任何特殊處理。
- 但容易與魔術(shù)方法混淆,因此官方建議避免這種命名。
注意:
- 不是魔術(shù)方法(魔術(shù)方法是
__xxx__) - 可能讓人誤以為是特殊用途
示例(不推薦):
class BadExample:
def _method_(self): # ? 看起來(lái)怪怪的,像拼寫(xiě)錯(cuò)誤
pass
?? PEP 8 建議:不要使用 _xxx_ 這種形式,除非你有非常特殊的理由。
4.__xxx__——魔術(shù)方法 / 特殊方法(Magic Methods)
含義:
- Python 保留給語(yǔ)言本身使用的特殊方法。
- 用于實(shí)現(xiàn)運(yùn)算符重載、內(nèi)置函數(shù)支持、對(duì)象協(xié)議等。
特點(diǎn):
- 由 Python 解釋器在特定場(chǎng)景自動(dòng)調(diào)用
- 永遠(yuǎn)不要自己發(fā)明 __xxx__ 名字(除非是文檔定義的標(biāo)準(zhǔn)方法)
示例:
class Vector:
def __init__(self, x):
self.x = x
def __add__(self, other): # 支持 +
return Vector(self.x + other.x)
def __str__(self): # 支持 str() 和 print()
return f"Vector({self.x})"
?? 用途:讓自定義對(duì)象支持
+,len(),print(),with,for等語(yǔ)言特性。
?? 重要:不要?jiǎng)?chuàng)建自己的
__my_custom_method__!這屬于 Python 保留命名空間。
總結(jié)對(duì)比表
| 命名形式 | 是否特殊處理 | 用途說(shuō)明 | 能否外部訪(fǎng)問(wèn) | 建議 |
|---|---|---|---|---|
_xxx | ? 否 | 內(nèi)部實(shí)現(xiàn)(約定) | ? 能 | 用作“受保護(hù)”成員 |
__xxx | ? 是(改名) | 避免子類(lèi)命名沖突(名稱(chēng)改寫(xiě)) | ? 能(改名后) | 用于真正需要隔離的內(nèi)部屬性 |
_xxx_ | ? 否 | 無(wú)特殊含義 | ? 能 | 避免使用 |
__xxx__ | ? 是 | 魔術(shù)方法(語(yǔ)言保留) | ? 能 | 只用于標(biāo)準(zhǔn)魔術(shù)方法 |
附加建議(來(lái)自 PEP 8)
__double_leading_and_trailing__: 僅用于魔術(shù)方法_single_leading_underscore: 表示內(nèi)部使用__double_leading_underscore: 觸發(fā)名稱(chēng)改寫(xiě)- 不要使用
_single_trailing_underscore_,除非是為了避免與關(guān)鍵字沖突(如class_)
記住一句話(huà):
“Python 給你自由,但也期望你遵守約定。”
下劃線(xiàn)不是鎖,而是禮貌的提醒。
到此這篇關(guān)于Python中單下劃線(xiàn)_ 、雙下劃線(xiàn)__的文章就介紹到這了,更多相關(guān) Python單下劃線(xiàn)_ 、雙下劃線(xiàn)__內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 淺談python 里面的單下劃線(xiàn)與雙下劃線(xiàn)的區(qū)別
- python中單下劃線(xiàn)(_)和雙下劃線(xiàn)(__)的特殊用法
- Python中的單下劃線(xiàn)和雙下劃線(xiàn)使用場(chǎng)景詳解
- Python中單下劃線(xiàn)和雙下劃線(xiàn)的使用詳解
- python?函數(shù)、變量中單下劃線(xiàn)和雙下劃線(xiàn)的區(qū)別詳解
- python中單下劃線(xiàn)與雙下劃線(xiàn)的區(qū)別及說(shuō)明
- python中的單下劃線(xiàn)與雙下劃線(xiàn)以及絕對(duì)導(dǎo)入與相對(duì)導(dǎo)入
- python單下劃線(xiàn)和雙下劃線(xiàn)屬性區(qū)別
相關(guān)文章
對(duì)pytorch網(wǎng)絡(luò)層結(jié)構(gòu)的數(shù)組化詳解
今天小編就為大家分享一篇對(duì)pytorch網(wǎng)絡(luò)層結(jié)構(gòu)的數(shù)組化詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-12-12
python運(yùn)行時(shí)強(qiáng)制刷新緩沖區(qū)的方法
今天小編就為大家分享一篇python運(yùn)行時(shí)強(qiáng)制刷新緩沖區(qū)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-01-01
Django框架中間件(Middleware)用法實(shí)例分析
這篇文章主要介紹了Django框架中間件(Middleware)用法,結(jié)合實(shí)例形式分析了Django框架中間件(Middleware)的功能、用法及相關(guān)操作技巧,需要的朋友可以參考下2019-05-05
Python+OpenCV 實(shí)現(xiàn)簡(jiǎn)單的高斯濾波(推薦)
這篇文章主要介紹了Python+OpenCV 實(shí)現(xiàn)簡(jiǎn)單的高斯濾波,在文中需要注意的是,這里我沒(méi)有特判當(dāng)sigma = 0的時(shí)候的情況,具體實(shí)現(xiàn)過(guò)程跟隨小編一起看看吧2021-09-09
python數(shù)據(jù)可視化之條形圖畫(huà)法
這篇文章主要為大家詳細(xì)介紹了python數(shù)據(jù)可視化之條形圖畫(huà)法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04
Python自動(dòng)化實(shí)戰(zhàn)之接口請(qǐng)求的實(shí)現(xiàn)
本文為大家重點(diǎn)介紹如何通過(guò) python 編碼來(lái)實(shí)現(xiàn)我們的接口測(cè)試以及通過(guò)Pycharm的實(shí)際應(yīng)用編寫(xiě)一個(gè)簡(jiǎn)單接口測(cè)試,感興趣的可以了解一下2022-05-05
Python中對(duì)數(shù)據(jù)庫(kù)的操作詳解
今天簡(jiǎn)單說(shuō)說(shuō)MySQL,我們存儲(chǔ)數(shù)據(jù),直接用本地文件即可,但是,本地文件不利于存放海量數(shù)據(jù),也不利于用程序?qū)ξ募臄?shù)據(jù)進(jìn)行查詢(xún)與管理,我們可以使用數(shù)據(jù)庫(kù)2023-02-02

