Python Coding Style

記錄一下我自己的 Python Coding Style,最近都照專案原本的 Coding Style 在寫,還是記錄一下,免得忘了自己 Style。

Coding Style Coding Style(圖片來源: orientation

Code Lay-out

縮排

Python 是用縮排來表示區塊的語言,所以最好保持縮排的一致,不然很容易出問題…。尤其是跟 Windows 的開發者 co-work 的時候,這個狀況更明顯,為了避免無謂的 diff ,依照 code style 建議改用 4 個空格取代 Tab,這個可以直接在 IDE 設定,把 Tab 的輸出換成 4 個空格即可。

單行字數

guideline 建議 79,只是我通常取整數設 80 。另外,如果有遇到縮排縮太深,導致字串超過螢幕,必須捲動下方捲才能閱讀的,我會直接換行,不過通常 IDE 會幫你把前面的空格一併記入字數計算

…是說如果縮排縮太深,應該要考慮重構了。

換行與對齊

當變數名稱太長或是參數太多,導致需要換行的時候,如果有第一個參數,對齊第一個參數;如果沒有,就縮排一次。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
## 如果有第一個參數,對齊第一個參數
self.train_batches = tdatagen.flow_from_directory(self.dataset_train_path,
                                                       target_size=self.image_size,
                                                       interpolation='bicubic',
                                                       class_mode=self.class_mode,
                                                       shuffle=True,
                                                       batch_size=self.batch_size)

## 如果沒有,就縮排一次
self.train_batches = datagen.flow_from_directory(
    self.dataset_train_path,
    target_size=self.image_size,
    interpolation='bicubic',
    class_mode=self.class_mode,
    shuffle=True,
    batch_size=self.batch_size)


如果是遇到計算式需要換行,則在運算子之前換行

1
2
3
4
5
income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

空行

最外層的函數或類別,兩兩之間用兩行隔開,類別內部的方法則用單行進行區隔。不過這我老是忘記,都會用自動排版幫忙校正。

Imports

一行一個 Import 模組,除非是用 Wildcard imports 才會把從同一個模組 imports 出來的東西寫在同一行。

1
2
3
import os
import sys
from subprocess import Popen, PIPE


另外 guideline 建議 import 要分群,每群之間使一行空白分隔,分群規則則按照:

  • 標準函式庫
  • 第三方函式庫
  • 本地端檔案及函式庫引用

不過我通常第一跟第二項都混成一群了…

String Quotes

在 python 中,字串單引號與雙引號都可以,但我偏愛先雙引號再單引號。

Whitespace in Expressions and Statements

與分隔符號及表達式間不用空白。

1
2
3
4
5
6
7
8
9
10
11
Yes: spam(ham[1], {eggs: 2})
No:  spam( ham[ 1 ], { eggs: 2 } )

Yes: foo = (0,)
No:  bar = (0, )
 
Yes: if x == 4: print x, y; x, y = y, x
No:  if x == 4 : print x , y ; x , y = y , x

Yes: spam(1)
No:  spam (1)


參數名稱與值之間也不用留白。

1
2
3
4
5
6
7
Yes:
def complex(real, imag=0.0):
    return magic(r=real, i=imag)

No:
def complex(real, imag = 0.0):
    return magic(r = real, i = imag)

不過我發現,如果有指定參數型態的話,IDE 又會建議加上空白 @@

1
2
3
4
5
6
7
Yes:
def complex(real, imag: float = 0.0):
        pass

No:
def complex(real, imag:float=0.0):
        pass


但我會在低優先權的運算子兩邊加上空白。

1
2
3
4
5
i = i + 1
submitted += 1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)

Naming Conventions

命名規則

  1. Modules and packages:小蛇式命名法(所有字都小寫,並用 _ 區隔), i.e. modules_name
  2. Globals and constants:大蛇式命名法(所有字都大寫,並用 _ 區隔), i.e. CONSTANT_NAME
  3. Class :大駝峰式命名法, i.e. ClassName
  4. Methods and functions:packages:小蛇式命名法
  5. Local variables:小蛇式命名法

底線開頭的變數

  1. _foo:
    類似 C/C++ 系列的 protected。無法被直接 import ,也不應該直接呼叫函數存取變數或存取變數,這邊 Python 沒禁止,但還是建議將它視為 protected 變數,不要在外部呼叫。最後與 protected 變數相同可以被子類別繼承。

    雖說是無法被 import ,但若是硬要 import 也不是做不到

    1
    2
     No: import *
     Yes: import _protected_func    
    
  2. __foo__:
    不要用!這是留給 Python builtin 專用的,用了小心哪天升級了後會爆炸 :bomb:

  3. __foo:
    這對應到的是 private 變數。只允許類別本身呼叫,無法被外部成員或是子類別直接操作與呼叫。

Linter

我慣用的 IDE 有兩個,分別是 Intellij IDEA 與 vscode。

如果在 Intellij IDEA 我通常會依賴內建自動排版來挑整一些縮排,並提供一些提示;但若在 vscode 我則是會額外安裝 Pylint 來輔助。

參考資料

  1. Style Guide for Python Code 。檢自 Python (2020-03-06)。
  2. subineru (2018-02-20)。Python 變數命名規則 。檢自 CJ Hung (2020-03-06)。
  3. 宅吉便 (2017-06-05)。Python,你到底是在__底線__什麼啦! 。檢自 宅吉便 (2020-03-06)。
  4. sooner高 (2017-05-07)。Python 类中Name mangling和下划线命名 。檢自 Python_g11d111的博客 - CSDN博客 (2020-03-06)。