本文為PEP: 8 Style Guide for Python Code的整理讶踪,用于規(guī)范python日常代碼粗恢。
1、縮進(jìn)與續(xù)航
(1)每一級(jí)縮進(jìn)使用4個(gè)空格魄缚。
雖然tab鍵用起來很爽暗甥,但規(guī)范角度而言喜滨,python的縮進(jìn)是4個(gè)空格,我們可以設(shè)置pycharm撤防,把Tab鍵設(shè)置成4個(gè)空格虽风。
(2)續(xù)行與包裹元素對(duì)齊
例如當(dāng)包裹元素為括號(hào)時(shí),續(xù)航與左括號(hào)對(duì)齊
# 正確寫法
foo = long_function_name(var_one, var_two,
var_three, var_four)
----------------------------------------------------------------------
# 錯(cuò)誤寫法
foo = long_function_name(var_one, var_two,
var_three, var_four)
(3)續(xù)航與運(yùn)算符位置
如果需要續(xù)航寄月,加減乘除運(yùn)算符在續(xù)航前還是續(xù)航后顯示辜膝?(蠻特別的!)
# 正確寫法
income = (gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction
- student_loan_interest)
----------------------------------------------------------------------
# 錯(cuò)誤寫法
income = (gross_wages +
taxable_interest +
(dividends - qualified_dividends) -
ira_deduction -
student_loan_interest)
2漾肮、行的最大長(zhǎng)度
(1)代碼行長(zhǎng)度
Python標(biāo)準(zhǔn)庫比較保守厂抖,需要將行寬限制在79個(gè)字符(文檔/注釋限制在72),當(dāng)然每次去算有沒有超過79個(gè)字符之類的肯定不合理的克懊,pycharm支持設(shè)置验游。
File→Settings→Code Style→Right margin (columns) 的值為79
(2)多用括號(hào)續(xù)航
- 較長(zhǎng)的代碼行選擇Python在小括號(hào),中括號(hào)以及大括號(hào)中的隱式續(xù)行方式
- 通過小括號(hào)內(nèi)表達(dá)式的換行方式將長(zhǎng)串折成多行保檐。這種方式應(yīng)該優(yōu)先使用,而不是使用反斜杠續(xù)行崔梗。
# 優(yōu)先使用括號(hào)續(xù)航
d = (a +
c)
----------------------------------------------------------------------
# 反斜杠續(xù)行
d = a + \
c
3夜只、空行行數(shù)
(1)空一行
- 用于類(class)成員函數(shù)之間。在同一個(gè)類中蒜魄,各個(gè)方法之間應(yīng)該用一個(gè)空行進(jìn)行分隔
- 或者用于區(qū)分不同邏輯塊扔亥,兩個(gè)邏輯無關(guān)段落間空一行
class Test(object):
"""Test class,提供通用的方法"""
def __init__(self):
"""Test的構(gòu)造器:"""
pass
def function1(self):
pass
def function2(self):
pass
(2)空兩行
用于類與類、類與函數(shù)谈为、函數(shù)與函數(shù)之間
class Test(object):
"""Test class,提供通用的方法"""
def __init__(self):
"""Test的構(gòu)造器:"""
pass
def function3():
pass
def function4():
pass
4旅挤、Imports 導(dǎo)入
(1)import位置
import 總是位于文件的頂部,在模塊注釋和文檔字符串之后伞鲫,在模塊的全局變量與常量之前粘茄。
不要東一個(gè)import,西一個(gè)import
(2)導(dǎo)入應(yīng)該按照以下順序分組
導(dǎo)入應(yīng)該按照以下順序分組:
a、標(biāo)準(zhǔn)庫導(dǎo)入(pyhon安裝的時(shí)候默認(rèn)自帶的庫:os,sys,re,math,random,datetime,...)[3]
b柒瓣、相關(guān)第三方庫導(dǎo)入(matplotlib,numpy,...)
c儒搭、本地應(yīng)用/庫特定導(dǎo)入(自建的一些庫,函數(shù)...)
之間空一行
import re
import sys
import matplotlib
import numpy
import mypackage
(3)避免通配符的導(dǎo)入
避免通配符的導(dǎo)入(from import *),因?yàn)檫@樣做會(huì)不知道命名空間中存在哪些名字芙贫,會(huì)使得讀取接口和許多自動(dòng)化工具之間產(chǎn)生混淆搂鲫。
通過 from M import * 導(dǎo)入的模塊應(yīng)該使用all機(jī)制去防止內(nèi)部的接口對(duì)外暴露
5、復(fù)合語句分開寫
復(fù)合語句(同一行中的多個(gè)語句)通常是不允許的磺平。
if/for/while語句中魂仍,即使執(zhí)行語句只有一句,也必須另起一行拣挪。
if foo == 'blah':
do_blah_thing()
do_one()
do_two()
do_three()
----------------------------------------------------------------------
# 錯(cuò)誤寫法
if foo == 'blah': do_blah_thing()
do_one(); do_two(); do_three()
6擦酌、空格的使用
(1)切片符號(hào) 前后的空格
# (1)不用空格
ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]
# (2)冒號(hào)前后用空格,把:當(dāng)做優(yōu)先級(jí)最低的操作;加號(hào)前后不加空格
ham[lower+offset : upper+offset]
(2)二元運(yùn)算符 前后的空格
二元運(yùn)算符兩邊加一個(gè)空格:賦值(=)媒吗,增量賦值(+=仑氛,-=),比較(==,<,>,!=,<>,<=,>=,in,not,in,is,is not)闸英,布爾(and, or, not)锯岖。
前后都要加空格
# =前后都加空格
x = 4
x > 3
----------------------------------------------------------------------
# 錯(cuò)誤寫法
x=4
x>3
不過不是所有場(chǎng)景的二元運(yùn)算符前后都要加空格的,有時(shí)候需要考慮優(yōu)先級(jí)甫何,在具有最低優(yōu)先級(jí)的運(yùn)算符周圍添加空格出吹。
# 先括號(hào)內(nèi)處理,然后乘法處理
c = (a+b) * (a-b)
----------------------------------------------------------------------
# 錯(cuò)誤寫法
c = (a + b) * (a - b)
關(guān)鍵字參數(shù)或者默認(rèn)參數(shù)值時(shí)辙喂,等號(hào)前后不加空格
# 這里的=前后不用空格的
def complex(real, imag=0.0):
return magic(r=real, i=imag)
(3)逗號(hào)/分號(hào)/冒號(hào) 后面加空格
逗號(hào)/分號(hào)/冒號(hào)后面加空格捶牢,前面緊貼參數(shù)
# 前面緊貼元素,后面一個(gè)空格
if x == 4: print x, y; x, y = y, x
----------------------------------------------------------------------
# 錯(cuò)誤寫法
if x == 4 : print x , y ; x , y = y , x
7巍耗、注釋
與代碼相矛盾的注釋比沒有注釋還糟秋麸,當(dāng)代碼更改時(shí),優(yōu)先更新對(duì)應(yīng)的注釋炬太!
塊注釋一般由完整句子的一個(gè)或多個(gè)段落組成灸蟆,并且每句話結(jié)束有個(gè)句號(hào)。
如果注釋很短亲族,結(jié)尾的句號(hào)可以省略
在句尾結(jié)束的時(shí)候應(yīng)該使用兩個(gè)空格
(1)塊注釋
塊注釋炒考,在一段代碼前增加的注釋。在‘#’后加一空格霎迫。段落之間以只有‘#’的行間隔斋枢。如果期間有空行,要加#的
# Description : Module config.
#
# Input : None
#
# Output : None
(2)行內(nèi)注釋
行內(nèi)注釋是與代碼語句同行的注釋知给,但是這種方式盡量少使用瓤帚。
行內(nèi)注釋和代碼至少要有兩個(gè)空格分隔,注釋由#和一個(gè)空格開始
x = x + 1 # Increment x
(3)文檔說明docstrings
要為所有的公共模塊,函數(shù)缘滥,類以及方法編寫文檔說明轰胁。
什么是文檔說明?朝扼?
非公共的方法沒有必要赃阀,但是應(yīng)該有一個(gè)描述方法具體作用的注釋,這個(gè)注釋應(yīng)該在def那一行之后擎颖。
多行文檔說明使用的結(jié)尾三引號(hào)應(yīng)該自成一行榛斯,對(duì)于單行的文檔說明,尾部的三引號(hào)應(yīng)該和文檔在同一行
# 多行文檔說明
"""Return a foobang
Optional plotz says to frobnicate the bizbaz first.
"""
# 單行文檔說明
"""Optional plotz says to frobnicate the bizbaz first."""
8搂捧、命名規(guī)范
那些暴露給用戶的API接口的命名驮俗,應(yīng)該遵循反映使用場(chǎng)景而不是實(shí)現(xiàn)的原則
(1)類名
類名一般使用首字母大寫的約定
class Lowercase:
# 還是
class LowerCase:
(2)變量、函數(shù)和屬性命名
變量允跑、函數(shù)和屬性應(yīng)該使用小寫字母來拼寫王凑,如果有多個(gè)單詞就使用下劃線進(jìn)行連接
lower_case_with_underscores # 使用下劃線分隔的小寫字母
如果函數(shù)的參數(shù)名和已有的關(guān)鍵詞沖突,在最后加單一下劃線比縮寫或隨意拼寫更好聋丝。因此 class_ 比 clss 更好
(3)模塊名
模塊與包
Python 模塊(Module)索烹,是一個(gè) Python 文件,以 .py 結(jié)尾
模塊應(yīng)該用簡(jiǎn)短全小寫的名字弱睦,如果為了提升可讀性百姓,下劃線也是可以用的;
包可能會(huì)包含多個(gè)模塊
Python包名也應(yīng)該使用簡(jiǎn)短全小寫的名字况木,但不建議用下劃線
例如自建一個(gè)包垒拢,包里面有模塊
from lowercase import case_with_underscores
(4)常量
常量通常定義在模塊級(jí),通過下劃線分隔的全大寫字母命名火惊。
例如: MAX_OVERFLOW 和 TOTAL
PI =3.141592653
SET_PI = 3.14
9求类、編程建議
(1)使用 is not ,而不是 not … is
使用 is not 運(yùn)算符屹耐,而不是 not … is尸疆。雖然這兩種表達(dá)式在功能上完全相同,但前者更易于閱讀张症,所以優(yōu)先考慮。
正確寫法:if foo is not None:
錯(cuò)誤寫法:if not foo is None:
(2)lambda不亂用
始終使用def表達(dá)式鸵贬,而不是通過賦值語句將lambda表達(dá)式綁定到一個(gè)變量上
正確寫法:def f(x): return 2*x
錯(cuò)誤寫法:f = lambda x: 2*x
(3)except異常
當(dāng)捕獲到異常時(shí)俗他,如果可以的話寫上具體的異常名,而不是只用一個(gè)except: 塊
# 寫出具體的異常名阔逼,例如“ImportError”
try:
import platform_specific_module
except ImportError:
platform_specific_module = None
(4)推薦使用try/except/else模式
對(duì)于所有的 try/except 語句塊兆衅,在try語句中只填充必要的代碼,這樣能避免掩蓋掉bug
try:
value = collection[key] # try中只填寫必要的代碼
except KeyError:
return key_not_found(key)
else:
return handle_value(value)
----------------------------------------------------------------------
# 錯(cuò)誤寫法
try:
return handle_value(collection[key])
except KeyError:
return key_not_found(key)
(5)return None
在沒有值可以返回的情況下,需要用 return None 顯式指明
def foo(x):
if x >= 0:
return math.sqrt(x)
else:
return None
# 或者
def bar(x):
if x < 0:
return None
return math.sqrt(x)
----------------------------------------------------------------------
# 錯(cuò)誤寫法(考慮不全面)
def foo(x):
if x >= 0:
return math.sqrt(x)
(6)startswith/endswith
使用 “.startswith() 和 ”.endswith() 代替通過字符串切割的方法去檢查前綴和后綴羡亩。startswith()和endswith()更干凈摩疑,出錯(cuò)幾率更小
正確寫法: if foo.startswith('bar'):
錯(cuò)誤寫法: if foo[:3] == 'bar':
(7)多用isinstance
對(duì)象類型的比較應(yīng)該用isinstance()而不是直接比較type
正確寫法: if isinstance(obj, int):
錯(cuò)誤寫法: if type(obj) is type(1):
(8)不是len(XX)>0
對(duì)于序列來說(strings,lists畏铆,tuples)不要用len去判斷雷袋;
對(duì)于布爾型變量來說,不要用 == 去和True或者False比較
# 如果存在內(nèi)容就運(yùn)行
正確寫法:if seq:
錯(cuò)誤寫法:if len(seq)>0:
# 如果不存在內(nèi)容就運(yùn)行
正確寫法:if not seq:
錯(cuò)誤寫法:if len(seq)=0:
# 布爾型
正確寫法:if greeting:
錯(cuò)誤寫法:if greeting == True:
錯(cuò)誤寫法:if greeting is True:
全文提到的“錯(cuò)誤寫法”是指就規(guī)范而言辞居,是不合適的寫法楷怒,并不是代碼運(yùn)行上的錯(cuò)誤,很多所謂的錯(cuò)誤寫法代碼還是可以運(yùn)行的瓦灶,只是那樣寫不是很規(guī)范鸠删,不夠?qū)I(yè)。
參考資料
[1] PEP: 8 Style Guide for Python Code:https://legacy.python.org/dev/peps/pep-0008/
[2] 中文版本:https://www.cnblogs.com/bymo/p/9567140.html
[3] python標(biāo)準(zhǔn)庫:https://docs.python.org/zh-cn/3/library/index.html