---
title: Python Coding Style
date: 2020-03-10
is_modified: false
disqus: cynthiahackmd
categories:
- "程式設計 › 程式語言與架構"
tags:
- "程式設計 › 程式語言與架構"
- "Coding Style"
- "Python"
---
{%hackmd @CynthiaChuang/Github-Page-Theme %}
<br>
記錄一下我自己的 Python Coding Style,最近都照專案原本的 Coding Style 在寫,還是記錄一下,免得忘了自己 Style。
<!--more-->
<p class="illustration">
<img src="https://i.imgur.com/8znl2lD.jpg" alt="Coding Style">
Coding Style(圖片來源: <a href="https://www.orientation-education.com/metier/developpeur-informatique">orientation</a>)
</p>
## Code Lay-out
### 縮排
Python 是用縮排來表示區塊的語言,所以最好保持縮排的一致,不然很容易出問題...。尤其是跟 Windows 的開發者 co-work 的時候,這個狀況更明顯,為了避免無謂的 `diff` ,依照 [code style](https://www.python.org/dev/peps/pep-0008/#code-lay-out) 建議改用 ==4 個空格取代 Tab==,這個可以直接在 IDE 設定,把 Tab 的輸出換成 4 個空格即可。
### 單行字數
guideline 建議 79,只是我通常取整數設 ==80== 。另外,如果有遇到縮排縮太深,導致字串超過螢幕,必須捲動下方捲才能閱讀的,我會直接換行,不過通常 IDE 會幫你把前面的空格一併記入字數計算
...是說如果縮排縮太深,應該要考慮重構了。
### 換行與對齊
當變數名稱太長或是參數太多,導致需要換行的時候,如果有第一個參數,對齊第一個參數;如果沒有,就縮排一次。
```python=
## 如果有第一個參數,對齊第一個參數
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)
```
<br> 如果是遇到計算式需要換行,則在運算子之前換行
```python
income = (gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction
- student_loan_interest)
```
### 空行
最外層的函數或類別,兩兩之間用==兩行==隔開,類別內部的方法則用==單行==進行區隔。不過這我老是忘記,都會用自動排版幫忙校正。
### Imports
==一行一個 Import 模組==,除非是用 Wildcard imports 才會把從同一個模組 imports 出來的東西寫在同一行。
```python=
import os
import sys
from subprocess import Popen, PIPE
```
<br> 另外 guideline 建議 ==import 要分群==,每群之間使一行空白分隔,分群規則則按照:
- 標準函式庫
- 第三方函式庫
- 本地端檔案及函式庫引用
不過我通常第一跟第二項都混成一群了...
## String Quotes
在 python 中,字串單引號與雙引號都可以,但我偏愛先==雙引號==再單引號。
## Whitespace in Expressions and Statements
與分隔符號及表達式間不用空白。
```python=
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)
```
<br> 參數名稱與值之間也不用留白。
```python=
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 又會建議加上空白 @@
```python=
Yes:
def complex(real, imag: float = 0.0):
pass
No:
def complex(real, imag:float=0.0):
pass
```
<br> 但我會在低優先權的運算子兩邊加上空白。
```python
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 也不是做不到
```python=
No: import *
Yes: import _protected_func
```
2. `__foo__`:
不要用!這是留給 ==Python builtin 專用的==,用了小心哪天升級了後會爆炸 :bomb:
3. `__foo`:
這對應到的是 ==private== 變數。只允許類別本身呼叫,無法被外部成員或是子類別直接操作與呼叫。
## Linter
我慣用的 IDE 有兩個,分別是 Intellij IDEA 與 vscode。
如果在 Intellij IDEA 我通常會依賴內建自動排版來挑整一些縮排,並提供一些提示;但若在 vscode 我則是會額外安裝 [Pylint](https://www.pylint.org/) 來輔助。
## 參考資料
1. [Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008/) 。檢自 Python (2020-03-06)。
2. subineru (2018-02-20)。[Python 變數命名規則](https://subineru.wordpress.com/2018/02/20/python-%E8%AE%8A%E6%95%B8%E5%91%BD%E5%90%8D%E8%A6%8F%E5%89%87/) 。檢自 CJ Hung (2020-03-06)。
3. 宅吉便 (2017-06-05)。[Python,你到底是在__底線__什麼啦!](https://aji.tw/python%E4%BD%A0%E5%88%B0%E5%BA%95%E6%98%AF%E5%9C%A8__%E5%BA%95%E7%B7%9A__%E4%BB%80%E9%BA%BC%E5%95%A6/) 。檢自 宅吉便 (2020-03-06)。
4. sooner高 (2017-05-07)。[Python 类中Name mangling和下划线命名](https://blog.csdn.net/g11d111/article/details/71367649) 。檢自 Python_g11d111的博客 - CSDN博客 (2020-03-06)。
<br><br>
> **本文作者**: 辛西亞.Cynthia
> **本文連結**: [辛西亞的技能樹](https://cynthiachuang.github.io/Python-Coding-Style) / [hackmd 版本](https://hackmd.io/@CynthiaChuang/Python-Coding-Style)
> **版權聲明**: 部落格中所有文章,均採用 [姓名標示-非商業性-相同方式分享 4.0 國際](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en) (CC BY-NC-SA 4.0) 許可協議。轉載請標明作者、連結與出處!