你真的懂Python命名嗎?

測試蔡坨坨 發表於 2022-06-26
Python

轉載請註明出處❤️

作者:測試蔡坨坨

原文連結:caituotuo.top/7417a7f0.html


大家好,我是測試蔡坨坨。

今天,我們來聊一下Python命名那些事兒。

名為萬物之始,萬物始於無名,道生一,一生二,二生三,三生萬物。

“怎麼給變數命名?”看似是一個非常基礎的內容,但還是有很多人在這個部分有一點迷茫。

命名常常被認為是程式設計中的細節問題,其重要性往往被低估。而所謂的工匠精神,往往體現在細節之處。

程式設計師在工作中有80%的時間都在閱讀和理解程式碼,好的命名可以提高程式碼的可讀性和表達力,詞不達意的命名則會讓人摸不著頭腦,增加不必要的思維開銷。

學好Python,從變數命名開始。

合法的變數名

什麼是合法的變數名?

所謂合法的變數名就是Python直譯器能夠認識的變數名。

也是在編碼過程中必須遵循的規則,假設不遵守規則,程式就會報錯。

在Python中,一個合法的變數名是由字母下劃線數字組成,並且第一個字元不能為數字。

在Python3中,對字母的定義其實是廣義的,你可以寫一箇中文的變數名,也就是說你可以認為中文的這個字也算一種字母,但是一般來說不推薦使用中文變數名,因為有時候可能會由於一些編碼的原因產生一些莫名其妙的bug。

caituotuo_666 = "測試蔡坨坨" # √
# 666caituotuo_666 = "測試蔡坨坨" # × 數字開頭不合法
蔡坨坨 = "測試蔡坨坨" # √ 不推薦

好的變數名

合法的變數名顯然給了我們很大的操作空間,我們可以給變數取各式各樣、千奇百怪的名字。

什麼是好的變數名?

好的變數名是一種命名規範,雖然不遵循命名規範,程式仍然可以執行,但是使用命名規範可以更加直觀地瞭解程式碼所代表的含義,因此和Python開發人員用同一套命名系統就顯得很重要。

我們可以從內容和形式上判斷一個變數名的好壞。

內容

從內容的角度就是這個變數名傳遞了多少有效資訊,是否是一個有意義的變數名。有意義的變數名可以達到程式碼即文件的效果,有較高的可讀性,不需要藉助註釋和文件,程式碼本身就能顯性地表達開發者的意圖。

例如以下三個變數:

n = "測試蔡坨坨"
name = "測試蔡坨坨"
username = "測試蔡坨坨"
  • 三個變數都代表使用者名稱
  • 相對於name,明顯username傳遞出來的有效資訊更多
  • 當你的變數名包含的有效資訊夠多的時候就是一個好的變數名

但是,是不是有效資訊越多越好,顯然並不是,我們還需要在有效資訊和變數名長度上做取捨(這二者之間的平衡取決於專案本身和經驗積累),不應該為了展示更多的資訊把變數名整的無限長,並不是一寸長一寸強,例如下面這個變數名就顯得過長了

student_system_login_username = "測試蔡坨坨"

形式

在編碼過程中,一個變數名有時候需要用到兩個及以上的單詞,當這些單詞擠在一起時,我們很難去分清誰是誰。所以在形式上我們又有四種不同的變數名寫法:

lower_underscore = "測試蔡坨坨"
UPPER_UNDERSCORE = "測試蔡坨坨"
CamelCase = "測試蔡坨坨"
mixedCase = "測試蔡坨坨"
  • lower_underscore:小寫字母跟下劃線
  • UPPER_UNDERSCORE:大寫字母跟下劃線
  • CamelCase:駝峰命名中的大駝峰,通過首字母大寫的方式來區別單詞
  • mixedCase:駝峰命名中的小駝峰,與大駝峰的區別就是第一個字母為小寫

推薦的變數名

什麼是被推薦的變數名?

Naming Convention 命名規範

在PEP8裡面就有比較詳細的描述,原文地址:https://peps.python.org/pep-0008/#naming-conventions

你真的懂Python命名嗎?

Naming Convention的核心就是consistency(一致性)

你真的懂Python命名嗎?

官方的意思大概是:

  • Python庫的命名規範有點亂,所以永遠不會完全一致
  • 儘管如此,還是有目前推薦的命名標準
  • 新的模組和包(包括第三方框架)應該按照這些標準編寫,但如果現有庫具有不同的風格,則優先考慮內部一致性

當你看到一個變數名的時候,如何快速分辨出是變數 or 常量 or 類 or 函式 or …?

就需要有一致性,也就是說好的變數不僅僅是讓你的程式變得好看,同時也能提高程式設計效率。

Python中使用的變數格式

在Python中用到的格式有三種:lower_underscore、UPPER_UNDERSCORE、CamelCase,不會用到mixedCase。

  • lower_underscore:小寫字母跟下劃線(除了常量和類名,剩下的所有名字都是小寫下劃線,包括:module模組variable變數function函式method方法,他們在Python中通常被看做是一個變數被使用、被傳遞,所以他們的命名方式是一致的)

  • UPPER_UNDERSCORE:大寫字母跟下劃線,只用來表示常量(其實在Python中並沒有真正的常量,更多的是一種約定,你別動我也別動,因此當你要表示常量的時候就可以用大寫下劃線,同時在Python標準庫中你看到大寫下劃線也就知道它是個常量)

    你真的懂Python命名嗎?

  • CamelCase:駝峰命名中的大駝峰,通過首字母大寫的方式來區別單詞,只用來表示

    你真的懂Python命名嗎?

  • mixedCase:駝峰命名中的小駝峰,與大駝峰的區別就是第一個字母為小寫(不會在Python中使用)

Python中的下劃線“_”

單下劃線 _

在Python直譯器中,對單下劃線是有特殊感情的。

  • 單下劃線也是Python中一個合法的變數名,通常被當做佔位符使用

    for _ in range(5):
        print("測試蔡坨坨")
        
    for i in range(5):
        print("測試蔡坨坨")
    

    從上面的程式可以看出,使用“_”比使用“i”表達出更多的資訊,就是顯性地告訴別人這個變數是沒有用的。

  • _ 會指向你最後一次執行的表示式

    你真的懂Python命名嗎?
  • 使用單個下劃線來格式化變數的值,例如金額,通過這樣的寫法我們能夠更加易讀

    total_value = 8_000_000_000
    print(total_value)  # 8000000000
    

前置下劃線 prefix

在Python中,前置下劃線在語義和功能上都有可能對變數本身造成一定的影響。

單前置下劃線 _xx

單下劃線在Python中叫弱私有(weak “internal use” ),在語義上表達的是private性質,也就是友好給告訴別人這並不是開放的介面,當你使用from module import * 的時候它是不會import單下劃線開頭的變數的,但是如果你強制使用它還是可以使用的,因此叫做弱私有。

class MyClass:
    def _get_name(self):
        print("測試蔡坨坨")

    def get_name(self):
        print("測試蔡坨坨")
你真的懂Python命名嗎?
雙前置下劃線 __xx

與弱私有相對應的就是強私有,在Python的class definition裡面用雙前置下劃線表示強私有,強行引用就會報錯,可以防止被子類重寫。

class MyClass:
    def __get_name(self):
        print("測試蔡坨坨")
你真的懂Python命名嗎?

其實強私有也是有辦法使用的,也就是防君子不妨小人,Python實際上是在class definition裡面對雙下劃線開頭的變數進行一個重新命名,就是在雙下劃變數的前面加一個_class名,如果列印的是obj._MyClass__get_name(),還是能正常執行的

你真的懂Python命名嗎?

後置下劃線 xx_

我們知道Python中有很多關鍵詞,例如:class、def、return、pass……,他們都有特殊的定義和意義,所以我們在定義變數或方法的時候不可以使用它們來命名,比如以下程式碼就是錯誤的:

# 錯誤示範
def my_func(pass):
    class = 1
    return class

如果我們就是想這樣定義名稱,為了區分,可以在後面新增一個下劃線(不過不建議這樣命名,雖然它是合法的,但是有那麼多名稱何必去定義關鍵詞相關的名稱呢)

def my_func(pass_):
    class_ = 1
    return class_

前後各有兩個下劃線 __xx__

你真的懂Python命名嗎?

dunderscore:double underscore

專門表示Python中的魔術函式magic method,都是一些Python內建好的一些函式,我們可以拿來就使用,例如:類的初始化方法__init____call__

對於Python使用者來說就是不要用,自己定義的方法永遠不要用到這種形式(Never invent such names; only use them as documented.)

其他注意事項

在起名的時候不要覆蓋Python中內建的方法(builtin method)

# 錯誤示範
list = [1, 2, 3, 4]  # ×
dict = {"username": "測試蔡坨坨"}  # ×
str = "測試蔡坨坨"  # ×

在給檔案起名的時候,也不要跟內建的module重名,例如:os.py、selenium.py、turtle.py,都是不可取的。