推薦:
# 與左括號對齊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)
# 懸掛縮進應該再換一行foo = long_function_name( var_one, var_two, var_three, var_four)不推薦:
# 沒有使用垂直對齊時,禁止把參數放在第一行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)可選:
# 懸掛縮進不一定要用4個空格foo = long_function_name( var_one, var_two, var_three, var_four)
# 沒有額外的縮進if (this_is_one_thing and that_is_another_thing): do_something()
# 增加一個注釋,在能提供語法高亮的編輯器中可以有一些區分if (this_is_one_thing and that_is_another_thing): # Since both conditions are true, we can frobnicate. do_something()
# 在條件判斷的語句添加額外的縮進if (this_is_one_thing and that_is_another_thing): do_something()
my_list = [ 1, 2, 3, 4, 5, 6, ]result = some_function_that_takes_arguments( 'a', 'b', 'c', 'd', 'e', 'f', )
my_list = [ 1, 2, 3, 4, 5, 6,]result = some_function_that_takes_arguments( 'a', 'b', 'c', 'd', 'e', 'f',)制表符Tab or 空格?
空格是首選的縮進方式。
制表符Tab只能用於與同樣使用制表符縮進的代碼保持一致。
Python3不允許同時使用空格和制表符的縮進。
混合使用制表符和空格縮進的Python2代碼應該統一轉成空格。
當在命令行加入-t選項執行Python2時,它會發出關於非法混用制表符與空格的警告。當使用–tt時,這些警告會變成錯誤。
即建議統一使用空格不要使用Tab。
行的最大長度所有行限制的最大字符數為79。
沒有結構化限制的大塊文本(文檔字符或者注釋),每行的最大字符數限制在72。
Python標準庫比較保守,需要將行寬限制在79個字符(文檔/注釋限制在72)。
較長的代碼行選擇Python在小括號,中括號以及大括號中的隱式續行方式。通過小括號內表達式的換行方式將長串折成多行。這種方式應該優先使用,而不是使用反斜槓續行。
反斜槓有時很有用。比如,比較長的,多個with狀態語句,不能使用隱式續行,反斜槓是可以接受的:
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())在二元運算符之前應該換行嗎?
推薦:
# 推薦原因:運算符和操作數很容易進行匹配income = (gross_wages + taxable_interest + (dividends - qualified_dividends) - ira_deduction - student_loan_interest)
不推薦:
# 不推薦原因: 操作符離操作數太遠income = (gross_wages + taxable_interest + (dividends - qualified_dividends) - ira_deduction - student_loan_interest)空行
例如:
class Test(object): """Test class,提供通用的方法""" def __init__(self): """Test的構造器:""" pass
def function1(self): pass
def function2(self): pass
def function3(): pass源文件編碼導入
推薦: import os import sys
不推薦: import sys, os
但是可以這樣:
from subprocess import Popen, PIPE
標準庫導入
相關第三方庫導入
本地應用/庫特定導入
建議在每種分組中根據每個模塊的完整包路徑按字典序排序, 忽略大小寫.
推薦使用絕對路徑導入,如果導入系統沒有正確的配置(比如包裡的一個目錄在sys.path裡的路徑後),使用絕對路徑會更加可讀並且性能更好(至少能提供更好的錯誤信息),例如:
import mypkg.siblingfrom mypkg import siblingfrom mypkg.sibling import example模塊級的「呆」名
像__all__ , __author__ , __version__ 等這樣的模塊級「呆名「(也就是名字裡有兩個前綴下劃線和兩個後綴下劃線),應該放在文檔字符串的後面,以及除from __future__ 之外的import表達式前面。Python要求將來在模塊中的導入,必須出現在除文檔字符串之外的其他代碼之前。
例如:
"""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 osimport sys字符串引號
在Python中,單引號和雙引號字符串是相同的。PEP不會為這個給出建議。選擇一條規則並堅持使用下去(這裡建議統一使用單引號)。當一個字符串中包含單引號或者雙引號字符的時候,使用和最外層不同的符號來避免使用反斜槓,從而提高可讀性。
對於三引號字符串,總是使用雙引號字符來與PEP 257中的文檔字符串約定保持一致。
表達式和語句中的空格空格使用要求在下列情況下,避免使用無關的空格:
Yes: spam(ham[1], {eggs: 2})No: spam( ham[ 1 ], { eggs: 2 } )
Yes: if x == 4: print x, y; x, y = y, xNo: if x == 4 : print x , y ; x , y = y , x
推薦:
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]
不推薦:
ham[lower + offset:upper + offset]ham[1: 9], ham[1 :9], ham[1:9 :3]ham[lower : : upper]ham[ : upper]
Yes: dct['key'] = lst[index]No: dct ['key'] = lst [index]
推薦:
x = 1y = 2long_variable = 3
不推薦:
x = 1y = 2long_variable = 3其他建議
避免在尾部添加空格。因為尾部的空格通常都看不見,會產生混亂:比如,一個反斜槓後面跟一個空格的換行符,不算續行標記。有些編輯器不會保留尾空格,並且很多項目(像CPython)在pre-commit的掛鈎調用中會過濾掉尾空格。
在二元運算符兩邊要各加一個空格:賦值(=),增量賦值(+=,-=),比較(==,<,>,!=,<>,<=,>=,in,not,in,is,is not),布爾(and, or, not)。
如果使用具有不同優先級的運算符,請考慮在具有最低優先級的運算符周圍添加空格。有時需要通過自己來判斷;但是,不要使用一個以上的空格,並且要在二元運算符的兩邊使用相同數量的空格。
推薦:
i = i + 1submitted += 1x = x*2 - 1hypot2 = x*x + y*yc = (a+b) * (a-b)
不推薦:
i=i+1submitted +=1x = x * 2 - 1hypot2 = x * x + y * yc = (a + b) * (a - b)
推薦:
def complex(real, imag=0.0): return magic(r=real, i=imag)不推薦:
def complex(real, imag = 0.0): return magic(r = real, i = imag)
推薦:
def munge(input: AnyStr): ...def munge() -> AnyStr: ...
不推薦:
def munge(input:AnyStr): ...def munge()->PosInt: ...
推薦:
def munge(sep: AnyStr = None): ...def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ...
不推薦:
def munge(input: AnyStr=None): ...def munge(input: AnyStr, limit = 1000): ...
推薦:
if foo == 'blah': do_blah_thing()do_one()do_two()do_three()
不推薦:
if foo == 'blah': do_blah_thing()do_one(); do_two(); do_three()
千萬別這樣:
if foo == 'blah': do_blah_thing()else: do_non_blah_thing()
try: something()finally: cleanup()
do_one(); do_two(); do_three(long, argument, list, like, this)
if foo == 'blah': one(); two(); three()注釋
與代碼相矛盾的注釋比沒有注釋還糟,當代碼更改時,優先更新對應的注釋!
注釋應該是完整的句子。如果一個注釋是一個短語或句子,它的第一個單詞應該大寫,除非它是以小寫字母開頭的標識符(永遠不要改變標識符的大小寫!)。
如果注釋很短,結尾的句號可以省略。塊注釋一般由完整句子的一個或多個段落組成,並且每句話結束有個句號。
在句尾結束的時候應該使用兩個空格
塊注釋行內注釋
但有時,這樣做很有用:
x = x + 1 # Compensate for border文檔字符串
PEP 257中關於文檔字符串的說明如下:
"""Return a foobang
Optional plotz says to frobnicate the bizbaz first."""命名規範
Python庫的命名規範很亂,從來沒能做到完全一致。但是目前有一些推薦的命名標準。新的模塊和包(包括第三方框架)應該用這套標準,但當一個已有庫採用了不同的風格,推薦保持內部一致性。
最重要的原則那些暴露給用戶的API接口的命名,應該遵循反映使用場景而不是實現的原則。
描述:命名風格有許多不同的命名風格。這裡能夠幫助大家識別正在使用什麼樣的命名風格,而不考慮他們為什麼使用。
以下是常見的命名方式:
b(單個小寫字母)
B(單個大寫字母)
lowercase 小寫字母
lower_case_with_underscores 使用下劃線分隔的小寫字母
UPPERCASE 大寫字母
UPPER_CASE_WITH_UNDERSCORES 使用下劃線分隔的大寫字母
CapitalizedWords(或者叫 CapWords,或者叫CamelCase 駝峰命名法 —— 這麼命名是因為字母看上去有起伏的外觀5)。有時候也被稱為StudlyCaps。
注意:當在首字母大寫的風格中用到縮寫時,所有縮寫的字母用大寫,因此,HTTPServerError 比 HttpServerError 好。mixedCase(不同於首字母大寫,第一個單詞的首字母小寫)
Capitalized_Words_With_Underscores(非常不美觀!)
X11庫的所有公共函數都加了前綴X。在Python裡面沒必要這麼做,因為屬性和方法在調用的時候都會用類名做前綴,函數名用模塊名做前綴。
另外,下面這種用前綴或結尾下劃線的特殊格式是被認可的(通常和一些約定相結合):
_single_leading_underscore:(單下劃線開頭)弱「內部使用」指示器。比如 from M import * 是不會導入以下劃線開始的對象的。
single_trailing_underscore_:(單下劃線結尾)這是避免和Python內部關鍵詞衝突的一種約定,比如:Tkinter.Toplevel(master, class_=』ClassName』)
__double_leading_underscore:(雙下劃線開頭)當這樣命名一個類的屬性時,調用它的時候名字會做矯正(在類FooBar中,__boo變成了_FooBar__boo;見下文)。
__double_leading_and_trailing_underscore__:(雙下劃線開頭,雙下劃線結尾)「magic」對象或者存在於用戶控制的命名空間內的屬性,例如:__init__,__import__或者__file__。除了作為文檔之外,永遠不要命這樣的名。
約定俗成:命名約定應避免的名字永遠不要使用字母『l』(小寫的L),『O』(大寫的O),或者『I』(大寫的I)作為單字符變量名。
因為在有些字體裡,這些字符無法和數字0和1區分,如果想用『l』,用『L』代替。
包名和模塊名模塊應該用簡短全小寫的名字,如果為了提升可讀性,下劃線也是可以用的。Python包名也應該使用簡短全小寫的名字,但不建議用下劃線。
類名類名一般使用首字母大寫的約定。
在接口被文檔化並且主要被用於調用的情況下,可以使用函數的命名風格代替。
注意,對於內置的變量命名有一個單獨的約定:大部分內置變量是單個單詞(或者兩個單詞連接在一起),首字母大寫的命名法只用於異常名或者內部的常量。
異常名因為異常一般都是類,所有類的命名方法在這裡也適用。然而,你需要在異常名後面加上「Error」後綴(如果異常確實是一個錯誤)
全局變量名(建議這一類變量只在模塊內部使用。)約定和函數命名規則一樣。
通過 from M import * 導入的模塊應該使用all機制去防止內部的接口對外暴露,或者使用在全局變量前加下劃線的方式(表明這些全局變量是模塊內非公有)。
函數名函數名應該小寫,如果想提高可讀性可以用下劃線分隔。
函數名字要有語義,最好是中文翻譯成英文,不要用拼音縮寫。
大小寫混合僅在為了兼容原來主要以大小寫混合風格的情況下使用
函數和方法參數始終要將 self 作為實例方法的的第一個參數。
始終要將 cls 作為類靜態方法的第一個參數。
如果函數的參數名和已有的關鍵詞衝突,在最後加單一下劃線比縮寫或隨意拼寫更好。因此 class_ 比 clss 更好。(也許最好用同義詞來避免這種衝突)
方法名和實例變量遵循這樣的函數命名規則:使用下劃線分隔小寫單詞以提高可讀性。
在非共有方法和實例變量前使用單下劃線。
通過雙下劃線前綴觸發Python的命名轉換規則來避免和子類的命名衝突。
常量常量通常定義在模塊級,通過下劃線分隔的全大寫字母命名。例如:MAX_OVERFLOW 和 TOTAL。
繼承的設計始終要考慮到一個類的方法和實例變量(統稱:屬性)應該是共有還是非共有。如果存在疑問,那就選非共有。因為將一個非共有變量轉為共有比反過來更容易。
以下是一些讓代碼Pythonic的準則:
公共屬性不應該有前綴下劃線。
如果公共屬性名和關鍵字衝突,在屬性名之後增加一個下劃線。這比縮寫和隨意拼寫好很多。(然而,儘管有這樣的規則,在作為參數或者變量時,『cls』是表示『類』最好的選擇,特別是作為類方法的第一個參數。)
注意1:參考之前的類方法參數命名建議對於單一的共有屬性數據,最好直接對外暴露它的變量名,而不是通過負責的 存取器(accessor)/突變(mutator) 方法。請記住,如果你發現一個簡單的屬性需要成長為一個功能行為,那麼Python為這種將來會出現的擴展提供了一個簡單的途徑。在這種情況下,使用屬性去隱藏屬性數據訪問背後的邏輯。
注意1:屬性只在new-style類中起作用。
注意2:儘管功能方法對於類似緩存的負面影響比較小,但還是要儘量避免。
注意3:屬性標記會讓調用者認為開銷(相當的)小,避免用屬性做開銷大的計算。如果你的類打算用來繼承的話,並且這個類裡有不希望子類使用的屬性,就要考慮使用雙下劃線前綴並且沒有後綴下劃線的命名方式。這會調用Python的命名轉換算法,將類的名字加入到屬性名裡。這樣做可以幫助避免在子類中不小心包含了相同的屬性名而產生的衝突。
公共和內部的接口
注意1:只有類名才會整合進屬性名,如果子類的屬性名和類名和父類都相同,那麼你還是會有命名衝突的問題。
注意2:命名轉換會在某些場景使用起來不太方便,例如調試,__getattr__()。然而命名轉換的算法有很好的文檔說明並且很好操作。
注意3:不是所有人都喜歡命名轉換。儘量避免意外的名字衝突和潛在的高級調用。任何向後兼容保證只適用於公共接口,因此,用戶清晰地區分公共接口和內部接口非常重要。
文檔化的接口被認為是公開的,除非文檔明確聲明它們是臨時或內部接口,不受通常的向後兼容性保證。所有未記錄的接口都應該是內部的。
為了更好地支持內省(introspection),模塊應該使用__all__屬性顯式地在它們的公共API中聲明名稱。將__all__設置為空列表表示模塊沒有公共API。
即使通過__all__設置過,內部接口(包,模塊,類,方法,屬性或其他名字)依然需要單個下劃線前綴。
如果一個命名空間(包,模塊,類)被認為是內部的,那麼包含它的接口也應該被認為是內部的。
導入的名稱應該始終被視作是一個實現的細節。其他模塊必須不能間接訪問這樣的名稱,除非它是包含它的模塊中有明確的文檔說明的API,例如 os.path 或者是一個包裡從子模塊公開函數接口的 __init__ 模塊。
編程建議代碼應該用不損害其他Python實現的方式去編寫(PyPy,Jython,IronPython,Cython,Psyco 等)。
比如,不要依賴於在CPython中高效的內置字符連接語句 a += b 或者 a = a + b。這種優化甚至在CPython中都是脆弱的(它只適用於某些類型)並且沒有出現在不使用引用計數的實現中。在性能要求比較高的庫中,可以種 」.join() 代替。這可以確保字符關聯在不同的實現中都可以以線性時間發生。和像None這樣的單例對象進行比較的時候應該始終用 is 或者 is not,永遠不要用等號運算符。
另外,如果你在寫 if x 的時候,請注意你是否表達的意思是 if x is not None。舉個例子,當測試一個默認值為None的變量或者參數是否被設置為其他值的時候。這個其他值應該是在上下文中能成為bool類型false的值。使用 is not 運算符,而不是 not … is 。雖然這兩種表達式在功能上完全相同,但前者更易於閱讀,所以優先考慮。
推薦:
不推薦:
推薦:
不推薦:
推薦: if foo.startswith('bar'):糟糕: if foo[:3] == 'bar':
正確: if isinstance(obj, int):糟糕: if type(obj) is type(1):
正確: if greeting:糟糕: if greeting == True:更糟: if greeting is True:腳註
[1]懸掛縮進是一種類型設置樣式,其中段落中除第一行外的所有行均縮進。在Python上下文中,該術語用於描述一種樣式,其中帶括號的語句的左括號是該行的最後一個非空白字符,其後的行會縮進,直到右括號為止。
文獻
http://legacy.python.org/dev/peps/pep-0008/
https://blog.csdn.net/ratsniper/article/details/78954852
回復 「免費課程」 完成任務免費獲取Python量化課程
回復 「量化禮包」 完成任務免費獲取珍藏量化禮包
回復 「量化教材」 獲取量化面試材料和量化教材
回復 「量化研報」 獲取量化投資研報
回復 「python書籍」 獲取Python學習書籍
StudyQuant - 站在巨人的肩膀上學習,項目制的在線量化投資學院。本學院基於新穎技術和人工智慧,打造量化交易體系和多元化量化投資策略,並在多個交易市場進行自營交易。我們旨在幫助零基礎的學員,通過幾個月的時間,系統掌握量化投資的專業技能,助力拿到高薪Offer。
回復 「免費課程」 完成任務免費獲取Python量化課程
回復 「量化禮包」 完成任務免費獲取珍藏量化禮包
回復 「量化教材」 獲取量化面試材料和量化教材
回復 「量化研報」 獲取量化投資研報
回復 「python書籍」 獲取Python學習書籍
StudyQuant - 站在巨人的肩膀上學習,項目制的在線量化投資學院。本學院基於新穎技術和人工智慧,打造量化交易體系和多元化量化投資策略,並在多個交易市場進行自營交易。我們旨在幫助零基礎的學員,通過幾個月的時間,系統掌握量化投資的專業技能,助力拿到高薪Offer。