詳解Python中的下劃線

PyPer發表於2015-03-13

本文將討論Python中下劃線(_)字元的使用方法。我們將會看到,正如Python中的很多事情,下劃線的不同用法大多數(並非所有)只是常用慣例而已。

單下劃線(_)

通常情況下,會在以下3種場景中使用:

1、在直譯器中:在這種情況下,“_”代表互動式直譯器會話中上一條執行的語句的結果。這種用法首先被標準CPython直譯器採用,然後其他型別的直譯器也先後採用。

2、作為一個名稱:這與上面一點稍微有些聯絡,此時“_”作為臨時性的名稱使用。這樣,當其他人閱讀你的程式碼時將會知道,你分配了一個特定的名稱,但是並不會在後面再次用到該名稱。例如,下面的例子中,你可能對迴圈計數中的實際值並不感興趣,此時就可以使用“_”。

3、國際化:也許你也曾看到”_“會被作為一個函式來使用。這種情況下,它通常用於實現國際化和本地化字串之間翻譯查詢的函式名稱,這似乎源自並遵循相應的C約定。例如,在Django文件“轉換”章節中,你將能看到如下程式碼:

可以發現,場景二和場景三中的使用方法可能會相互衝突,所以我們需要避免在使用“_”作為國際化查詢轉換功能的程式碼塊中同時使用“_”作為臨時名稱。

名稱前的單下劃線(如:_shahriar)

程式設計師使用名稱前的單下劃線,用於指定該名稱屬性為“私有”。這有點類似於慣例,為了使其他人(或你自己)使用這些程式碼時將會知道以“_”開頭的名稱只供內部使用。正如Python文件中所述:

以下劃線“_”為字首的名稱(如_spam)應該被視為API中非公開的部分(不管是函式、方法還是資料成員)。此時,應該將它們看作是一種實現細節,在修改它們時無需對外部通知。

正如上面所說,這確實類似一種慣例,因為它對直譯器來說確實有一定的意義,如果你寫了程式碼“from <模組/包名> import *”,那麼以“_”開頭的名稱都不會被匯入,除非模組或包中的“__all__”列表顯式地包含了它們。瞭解更多請檢視“Importing * in Python”。

名稱前的雙下劃線(如:__shahriar)

名稱(具體為一個方法名)前雙下劃線(__)的用法並不是一種慣例,對直譯器來說它有特定的意義。Python中的這種用法是為了避免與子類定義的名稱衝突。Python文件指出,“__spam”這種形式(至少兩個前導下劃線,最多一個後續下劃線)的任何識別符號將會被“_classname__spam”這種形式原文取代,在這裡“classname”是去掉前導下劃線的當前類名。例如下面的例子:

正如所預料的,“_internal_use”並未改變,而“__method_name”卻被變成了“_ClassName__method_name”。此時,如果你建立A的一個子類B,那麼你將不能輕易地覆寫A中的方法“__method_name”。

這裡的功能幾乎和Java中的final方法和C++類中標準方法(非虛方法)一樣。

名稱前後的雙下劃線(如:__init__)

這種用法表示Python中特殊的方法名。其實,這只是一種慣例,對Python系統來說,這將確保不會與使用者自定義的名稱衝突。通常,你將會覆寫這些方法,並在裡面實現你所需要的功能,以便Python呼叫它們。例如,當定義一個類時,你經常會覆寫“__init__”方法。

雖然你也可以編寫自己的特殊方法名,但不要這樣做。

其實,很容易擺脫這種型別的命名,而只讓Python內部定義的特殊名稱遵循這種約定。

相關文章