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

