PEP8

代碼布局

縮進

推薦的兩種方式:

  • 垂直對齊:與(), [], {}對齊
  • 懸掛縮進

建議


# 垂直對齊嘶炭,與外面(), [], {}對齊
foo = long_function_name(var_one, var_two,
                         var_three, var_four)

# 懸掛縮進得运,以行開頭作為參考
foo = long_function_name(
    var_one, var_two,
    var_three, var_four)
    
    
# 為了和函數(shù)體區(qū)分開蟹漓,采用更多的縮進
def long_function_name(
        var_one, var_two, var_three,
        var_four):
    print(var_one)

不建議

# 如果使用懸掛縮進而不是垂直對齊链快,第一行就不要有參數(shù)铣耘。
foo = long_function_name(var_one, var_two,
    var_three, var_four)

# 
def long_function_name(
    var_one, var_two, var_three,
    var_four):
    print(var_one)

括號結束的處理

  • 可以在最后一個元素后面
  • 可以和語句開頭第一個字符對齊
  • 可以和上一行第一個不為空格的字符對齊
# 和上一行的第一個不為空格的字符對齊
result = some_function_that_takes_arguments(
    'a', 'b', 'c',
    'd', 'e', 'f',
    )
# 和語句開頭的第一個字符對齊
my_list = [
    1, 2, 3,
    4, 5, 6,
]

if語句的縮進

# 無額外的縮進.
if (this_is_one_thing and
    that_is_another_thing):
    do_something()

# 添加一條注釋來分隔if語句的兩個部分
# supporting syntax highlighting.
if (this_is_one_thing and
    that_is_another_thing):
    # Since both conditions are true, we can frobnicate.
    do_something()

# 添加額外的縮進來分隔if語句的兩個部分
if (this_is_one_thing
        and that_is_another_thing):
    do_something()

Tab還是空格

  • 推薦使用空格
  • 只有在兼容的時候使用Tab
  • Python 3不允許兩者混合使用诺苹。
  • Python 2用選項-t 可以在混合使用的時候發(fā)出警告抛姑;使用選項-tt會發(fā)出錯誤卓嫂。

單行的最大長度

79個字符。

對于docstring和注釋:72個字符蜈项。

好處:

  • 在屏幕兩邊同時打開不同文件
  • 代碼評審時芹关,在屏幕兩側對比同一文件的不同版本

實踐:

  • 一致就好
  • 能不使用反斜杠就不使用:用括號將內容括起來。
with open('/path/to/some/file/you/want/to/read') as file_1, \
     open('/path/to/some/file/being/written', 'w') as file_2:
    file_2.write(file_1.read())

換行到底在二元操作符前面還是后面紧卒?

# No: operators sit far away from their operands
income = (gross_wages +
          taxable_interest +
          (dividends - qualified_dividends) -
          ira_deduction -
          student_loan_interest)

# Yes: easy to match operators with operands
income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

空行

  • 頂層的函數(shù)侥衬、類用兩個空行分隔
  • 類內部的方法定義用一個空行分隔
  • 在函數(shù)內部使用空行表示邏輯的分塊
  • 可以使用control-L作為換頁符,貌似pycharm并不支持

文件編碼

UTF-8

import語句

  • 分開使用
# Yes: 
import os
import sys

# No:
import sys, os

# OK:
from subprocess import Popen, PIPE

  • 在文件最上方:模塊注釋和docstring之后跑芳,globals和常量之前轴总。順尋應該是(每組之間用空行隔開):
    1. 標準庫
    2. 相關的第三方庫
    3. 本地庫
  • 導入一個類時:
from myclass import MyClass
from foo.bar.yourclass import YourClass

# 如果類名有沖突
import myclass
import foo.bar.yourclass

# 使用時:"myclass.MyClass"  "foo.bar.yourclass.YourClass".
  • 盡量避免import mypkg.*

模塊級的dunder name

模塊級的dunder name博个,比如__all__, __version__, __author__應該放在import之前怀樟,但是在from __future__ import之后,因為這一句是強制要求在所有代碼之前的盆佣。

"""This is the example module.

This module does stuff.
"""

from __future__ import barry_as_FLUFL

__all__ = ['a', 'b', 'c']
__version__ = '0.1'
__author__ = 'Cardinal Biggles'

import os
import sys

字符串的引號

單引號雙引號都可以往堡,那么選擇一個,然后保持一致共耍。

表達式和語句中的空格

一定不要這么做虑灰!

  • 括號內,緊挨括號的地方痹兜,不要加空格
# Yes: 
spam(ham[1], {eggs: 2})
foo = (0,)

# No:  
spam( ham[ 1 ], { eggs: 2 } )
bar = (0, )
  • , ; :之前穆咐,不要加空格
# Yes: 
if x == 4: print x, y; x, y = y, x
# No:  
if x == 4 : print x , y ; x , y = y , x
  • 在切片中使用:的時候,把它當作一個操作符來考慮:兩邊使用同樣多的空格字旭。例外:如果切片中有的參數(shù)省略了庸娱,那么該參數(shù)的空格也要省略
# 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]
  • 參數(shù)列表的小括號(之前,不要加空格
# Yes: 
spam(1)
foo = (0, 1)

# No:
spam (1)
  • 索引或切片操作的中括號[之前谐算,不要加空格
# Yes: 
dct['key'] = lst[index]
# No:  
dct ['key'] = lst [index]
  • 賦值操作符前后只要一個空格,不要用過多的空格來對齊
# Yes:
x = 1
y = 2
long_variable = 3

# No:
x             = 1
y             = 2
long_variable = 3

其他的建議

  • 行尾不要有空格
  • 為下列二維操作符的前后各加一個空格:賦值归露、比較洲脂、booleans
  • 在同一句語句中剧包,可以省略優(yōu)先級較高的操作符之間的空格恐锦。二元操作符前后的數(shù)量一定要相等,一定不要超過一個疆液。
  • 關鍵字參數(shù)和默認參數(shù)中的=前后不要加空格
# 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)
  • 函數(shù)和參數(shù)的注解:冒號:前無空格一铅,后跟空格;->前后各一個空格堕油;既有注解又有默認值時潘飘,等號=前后各一個空格肮之。
# Yes:
def munge(sep: AnyStr = None): ...
def munge() -> AnyStr: ...
def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ...
# No:
def munge(input: AnyStr=None): ...
def munge()->PosInt: ...
def munge(input: AnyStr, limit = 1000): ...

什么時候使用結尾的逗號

  • 只有一個元素的tuple。這種情況最好使用括號卜录。
# Yes:
FILES = ('setup.cfg',)

# OK
FILES = 'setup.cfg',
  • 在一個值占一行戈擒,且右括號)]}單獨占一行的情況,可以加一個多于的逗號在句尾艰毒】鸶撸可以方便diff
# Yes:
FILES = [
    'setup.cfg',
    'tox.ini',
    ]
initialize(FILES,
           error=True,
           )

# No:
FILES = ['setup.cfg', 'tox.ini',]
initialize(FILES, error=True,)

注釋

  • 不要與代碼矛盾丑瞧!改代碼也要改注釋
  • 塊注釋必須由完整的句子組成柑土,用句號分隔
  • 最好用英文

行內注釋

  • 不要太多
  • 與語句至少2個空格,#后跟一個空格绊汹。

文檔字符串 docstrings

  • 為公共的模塊稽屏、函數(shù)、類灸促、方法寫注釋诫欠。
  • 格式
"""Return a foobang

Optional plotz says to frobnicate the bizbaz first.
"""

命名規(guī)范

讓所有代碼都遵守一致的命名規(guī)范很難的,可以要求新的模塊和包遵守一定的規(guī)范浴栽,但已有的庫可能不滿足荒叼,這時候需要在內部保持一致。

首要原則

對外的接口典鸡,要反映usage被廓,而不是implementation

常見的命名方式

  • b
  • B
  • lowercase
  • lower_case_with_underscores
  • UPPERCASE
  • UPPER_CASE_WITH_UNDERSCORES
  • CapitalizedWords
  • mixedCase
  • Capitalized_Words_With_Underscores
    Python中的一些約定
  • _single_leading_underscore
  • single_trailing_underscore_
  • __double_leading_underscore
  • __double_leading_and_trailing_underscore__

規(guī)范

  • 模塊名:小寫字母+下劃線
  • 包名:小寫字母。e.g. timeit
  • 類名:首字母大寫萝玷。e.g. CapWords
  • 異常名:首字母大寫+后綴Error
  • 函數(shù)名嫁乘、變量名、方法名球碉、實例變量名:小寫+下劃線
  • 參數(shù)名:小寫+下劃線蜓斧;selfcls是約定;與關鍵字沖突的時候睁冬,在后面加_
  • 常量:大寫字母+下劃線

繼承的設計

  • 公共屬性不要以下劃線開頭挎春。
  • 如果屬性與關鍵字沖突,在結尾地方加一個下劃線豆拨。
  • 對public的數(shù)據(jù)屬性直奋,最好不要getter/setter(accessor/mutator)方法。
  • 如果有屬性不想讓子類使用施禾,則命名為__foo脚线,觸發(fā)python的命名轉換。

公共接口和內部接口

  • 必須保證公共接口向后兼容弥搞,對內部接口則不用
  • 必須為公共借口提供文檔
  • 使用all聲明公共接口
  • 內部接口(包邮绿、模塊渠旁、類、函數(shù)等)使用前綴_

編程建議

  • 不要依賴與具體的python實現(xiàn)(PyPy, Jython, IronPython, Cython)
  • 與單例對象(比如None)作比較的時候斯碌,用isis not一死,而不是==
  • 使用is not而不是not ... is傻唾。
# Yes:
if foo is not None:
    ...
# No:
if not foo is None:
    ...
  • 使用def投慈,而不是賦值+lambda
  • python2中冠骄,用raise ValueError('message')代替raise ValueError, 'message'伪煤。后者在python3是錯誤的。
  • expect指明異常類型凛辣,需要異常名時抱既,使用as
try:
    foo()
expect Exception as exc:
    print(exc)
  • try語句塊內的語句盡可能的少扁誓。
  • 局部使用的資源防泵,使用with

自動格式化的工具

black

  • 基于python3蝗敢,可以格式化python2的代碼
  • 比較專制捷泞,遵守pep8/pycodestyle
  • 默認全部使用雙引號(為啥?)寿谴,可以用選項--skip-string-normalization來跳過锁右,不更改字符串的引號。
  • 在列表最后項的末尾加了多于的逗號,
  • 去除不必要的反斜杠\
  • 過長的字符串不做處理
  • 列表太多太長時:一項獨占一行
  • # fmt: off# fmt: on來標記不需要format的語句塊讶泰,兼容yapf的標記咏瑟。
  • make pycodestyle happy. PEP8的子集
  • 在二元操作符前換行
  • 切片:PEP8

如何處理折行?

1. 嘗試不折行
2. 打開最外層括號痪署,括號內內容單獨一行
3. 還是不行码泞,迭代打開括號
4. 如果內容沒有括號,有逗號做分隔狼犯,嘗試同一行
5. 放不下->每一項獨占一行余寥,并加一個多于的逗號。(便于diff)
# in:

def very_important_function(template: str, *variables, file: os.PathLike, debug: bool = False):
    """Applies `variables` to the `template` and writes to `file`."""
    with open(file, 'w') as f:
        ...

# out:

def very_important_function(
    template: str,
    *variables,
    file: os.PathLike,
    debug: bool = False,
):
    """Applies `variables` to the `template` and writes to `file`."""
    with open(file, "w") as f:
        ...

行的長度

默認88辜王,為了讓文件長度更短。
尺有所短寸有所長罐孝。

空行

遵循PEP8呐馆。

  • 在函數(shù)前后插入一個空行,在模塊級的類和函數(shù)的前后插入兩個空行莲兢。
  • 類的docstrings后緊跟一個空行
  • 函數(shù)的docstrings后一般不跟空行汹来,除非后面緊跟一個內部函數(shù)续膳。

tailing commas

  • 在獨占一行的時候添加

isort

自動給import語句排序。

靜態(tài)代碼分析工具

pycodestyle

原名pep8收班。參照PEP 8坟岔。定義了Error codes

Pylint
flake8

formatter

yapf
black
  • “驕傲”
autopep8
  • 使用pycodestyle來決定需要格式化的代碼摔桦,修復它報的大部分格式問題社付。
  • 默認,只做空格空行的增減邻耕,不會修正 x == None鸥咖。加選項--agressive
  • --select修正指定的錯誤/警告兄世。
  • 可以作為模塊使用啼辣。
  • PEP 8pycodestyle為導向
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市御滩,隨后出現(xiàn)的幾起案子鸥拧,更是在濱河造成了極大的恐慌,老刑警劉巖削解,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件富弦,死亡現(xiàn)場離奇詭異,居然都是意外死亡钠绍,警方通過查閱死者的電腦和手機舆声,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來柳爽,“玉大人媳握,你說我怎么就攤上這事×赘” “怎么了蛾找?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長赵誓。 經(jīng)常有香客問我打毛,道長,這世上最難降的妖魔是什么俩功? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任幻枉,我火速辦了婚禮,結果婚禮上诡蜓,老公的妹妹穿的比我還像新娘熬甫。我一直安慰自己,他們只是感情好蔓罚,可當我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布椿肩。 她就那樣靜靜地躺著瞻颂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪郑象。 梳的紋絲不亂的頭發(fā)上贡这,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天,我揣著相機與錄音厂榛,去河邊找鬼盖矫。 笑死,一個胖子當著我的面吹牛噪沙,可吹牛的內容都是我干的炼彪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼正歼,長吁一口氣:“原來是場噩夢啊……” “哼辐马!你這毒婦竟也來了?” 一聲冷哼從身側響起局义,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤喜爷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后萄唇,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體檩帐,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年另萤,在試婚紗的時候發(fā)現(xiàn)自己被綠了湃密。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡四敞,死狀恐怖泛源,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情忿危,我是刑警寧澤达箍,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站铺厨,受9級特大地震影響缎玫,放射性物質發(fā)生泄漏。R本人自食惡果不足惜解滓,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一赃磨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧洼裤,春花似錦邻辉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至缕减,卻和暖如春雷客,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背桥狡。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工搅裙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人裹芝。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓部逮,卻偏偏與公主長得像户敬,于是被迫代替她去往敵國和親藏澳。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內容