統一且設計良好的代碼規範,是一種優良的編程習慣。
PyCharm這一Python IDE使用的正是著名的PEP8代碼規範,我們會看到,當有不符合規範的代碼出現時,編譯器會以灰色下劃波浪線給出相關提示,本文即告訴你如何寫出沒有灰色警告線的至少看上去很美的代碼樣式。
縮排(indentation)
使用四個空格表示每個縮排層級。
Yes
# 使用開分隔字元(opening delimiter)進行對齊foo = long_func_name(var_one, var_two, var_three, var_four)# 使用更多的縮排以和其他的代碼單元區別開來# 如下例的,參數部分比函數體多四個縮排以和函數體進行區別def long_func_name( var_one, var_two, var_three, var_four) print(var_one)# 首行凸排(hanging indents):增加一個縮排層級foo = long_func_name( var_one, var_two, var_three, var_four)# 或者:foo = long_func_name( var_one, var_two, var_three, var_four)a = [1, 2, 3, 4, 5, 6]a = [ 1, 2, 3, 4, 5, 6]
No
# 當不適用垂直對齊時,禁止在第一行使用參數# 換句話說,在垂直對齊時,才可在第一行使用參數foo = lone_func_name(var_one, var_two, var_three, var_four)# 當縮排不足以區分代碼結構時,增加一個縮排層級def long_func_name( var_one, var_two, var_three var_four): print(var_one)
最大行長度
所有行的最大長度均為79個字元。
with open('') as file_1, \ open('') as file_2: file_2.write(file_1.read())
使用正確的換行位置。推薦的位置在二元操作符(binary operator,如下述代碼中的and、or以及%)之後,而不是在它們之前:
class Rectangle(Shape): def __init__(self, width, height, color='black', emphasis=None, highlight=0): if (width == 0 and height == 0 and color == 'red' and emphasis == 'strong' or height > 100): raise ValueError("sorry, you lose") if width == 0 and height == 0 and (color == 'red' or emphasis is None): raise ValueError("I don't think so -- values are %s, %s" % (width, height)) Shape.__init__(self, width, height, color, emphasis, highlight)
空行
頂級函數(當前檔案中的第一個函數)或者頂級類(當前檔案的第一個類)之前要有兩個空行
定義在類內部的函數(成員函數)之間要留有一個空行
可以使用額外的空行(但要注意節制)以區分不同的函數組,
在一堆只有一行的函數之間不要使用空行(比如一些函數的空實現)
在函數內部使用空行,來標識不同的邏輯單元 imports 在獨立的行中匯入不同的包
Yes
import sysimport os
No
import sys, os
但從一個包中添加不同的模組或者函數也是允許的:
from subprocess import Popen, PIPE
import檔案應當總是位於檔案的首部,僅在模組備忘和文檔之後,在模組的全域變數和常量之前的位置
import檔案的順序:
1. 標準庫(如sys、os)
2. 相關的第三方的庫(如numpy、pandas、matplotlib)
3. 自訂的.py檔案或者自訂的庫
以組的形式標識上述三種import檔案,也即是用一個空行隔開 推薦使用絕對路徑包含,因為可讀性更好,並且不易出錯。
import mypkg.siblingfrom mypkg import sibling from mypkg.sibling import example
然而,外部的相對包含也是一種可接受的替換,尤其是處理複雜的包層次時,也即是絕對包含將造成不必要的繁瑣。
from . import siblingfrom .sibling import example # .表示當前路徑
標準庫不存在複雜的包層次關係,應當總是使用其絕對匯入路徑。 應當避免萬用字元匯入檔案 字串
在python中,不對單引號和雙引號作區分,PEP的代碼規範也不對此有所推薦。任選其一,統一使用即可。然而,當一個字串包含單引號或者雙引號時,使用另外一種方式避免轉義符(\)的使用,以提高可讀性。 運算式中的空格
在下述條件下,避免使用空格: 緊跟著大括弧、中括弧和小括弧之前
Yes
spam(ham[1], {eggs: 90})
No
spam( ham [ 1 ], { eggs: 2 })
緊連著逗號、分號、冒號之前
Yes
if x == 4: print x, y; x, y = y, x
NO
if x == 4 : print x , y ; x , y = y , x
切片中的冒號
在切片中冒號可視為一個二元操作符(binary operator),兩邊應用等數量的空格。
Yes
ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]ham[lower:upper], ham[lower:upper:], ham[lower::step]ham[lower+offset : upper+offset]ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]ham[lower + offset : upper + offset]
No
ham[lower + offset:upper + offset]ham[1: 9], ham[1 :9], ham[1:9 :3]ham[lower : : upper]ham[ : upper]
其他的建議
總是在如下的二元操作符的兩邊使用單空格: 賦值:= 增量賦值:+=, -= 比較:==, <, >, !=, <>, in , is 布爾:and, or, not
不要使用空格,當被用來標識一個關鍵字參數(使用函數)或者一個預設參數賦值(定義函數)
Yes
def complex(real, imag=0.): return magic(r=real, i=imag)
No
def complex(real, imag = 0.): return magic(r = real, i = imag)
文檔
為所有公用模組或者函數、類以及方法編寫文檔。不必為非公用方法編寫doc文檔,但應有一個注釋描述演算法的功能,這條注釋應當出現在def之後
結尾的"""應當獨佔一行
"""Return a foobangOptional plotz says to frobnicate the bizbaz first."""
References
[1] <PEP 0008 – Style Guide for Python Code>