英文原文:PEP 8 -- Style Guide for Python Codepython
PEP: | 8 |
---|---|
Title: | Style Guide for Python Code |
Version: | c451868df657 |
Last-Modified: | 2016-06-08 10:43:53 -0400 (Wed, 08 Jun 2016) |
Author: | Guido van Rossum <guido at python.org>, Barry Warsaw <barry at python.org>, Nick Coghlan <ncoghlan at gmail.com> |
Status: | Active |
Type: | Process |
Content-Type: | text/x-rst |
Created: | 05-Jul-2001 |
Post-History: | 05-Jul-2001, 01-Aug-2013 |
本文提供的Python代碼編碼規範基於Python主要發行版本的標準庫。Python的C語言實現的C代碼規範請查看相應的PEP指南1。git
這篇文檔以及PEP 257(文檔字符串的規範)改編自Guido原始的《Python Style Guide》一文,同時添加了一些來自Barry的風格指南2。程序員
這篇規範指南隨着時間的推移而逐漸演變,隨着語言自己的變化,過去的約定也被淘汰了。github
許多項目有本身的編碼規範,在出現規範衝突時,項目自身的規範優先。算法
Guido的一條重要的看法是代碼閱讀比寫更加頻繁。這裏提供的指導原則主要用於提高代碼的可讀性,使得在大量的Python代碼中保持一致。就像PEP 20提到的,「Readability counts」。編程
這是一份關於一致性的風格指南。這份風格指南的風格一致性是很是重要的。更重要的是項目的風格一致性。在一個模塊或函數的風格一致性是最重要的。api
然而,應該知道何時應該不一致,有時候編碼規範的建議並不適用。當存在模棱兩可的狀況時,使用本身的判斷。看看其餘的示例再決定哪種是最好的,不要羞於發問。緩存
特別是不要爲了遵照PEP約定而破壞兼容性!框架
幾個很好的理由去忽略特定的規則:socket
每一級縮進使用4個空格。
續行應該與其包裹元素對齊,要麼使用圓括號、方括號和花括號內的隱式行鏈接來垂直對齊,要麼使用掛行縮進對齊3。當使用掛行縮進時,應該考慮到第一行不該該有參數,以及使用縮進以區分本身是續行。
推薦:
# 與左括號對齊 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語句的條件部分長到須要換行寫的時候,注意能夠在兩個字符關鍵字的鏈接處(好比if),增長一個空格,再增長一個左括號來創造一個4空格縮進的多行條件。這會與if語句內一樣使用4空格縮進的代碼產生視覺衝突。PEP沒有明確指明要如何區分i發的條件代碼和內嵌代碼。可以使用的選項包括但不限於下面幾種狀況:
# 沒有額外的縮進 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', )
空格是首選的縮進方式。
製表符只能用於與一樣使用製表符縮進的代碼保持一致。
Python3不容許同時使用空格和製表符的縮進。
混合使用製表符和空格縮進的Python2代碼應該統一轉成空格。
當在命令行加入-t選項執行Python2時,它會發出關於非法混用製表符與空格的警告。當使用–tt時,這些警告會變成錯誤。強烈建議使用這樣的參數。
全部行限制的最大字符數爲79。
沒有結構化限制的大塊文本(文檔字符或者註釋),每行的最大字符數限制在72。
限制編輯器窗口寬度可使多個文件並行打開,而且在使用代碼檢查工具(在相鄰列中顯示這兩個版本)時工做得很好。
大多數工具中的默認封裝破壞了代碼的可視化結構,使代碼更難以理解。避免使用編輯器中默認配置的80窗口寬度,即便工具在幫你折行時在最後一列放了一個標記符。某些基於Web的工具可能根本不提供動態折行。
一些團隊更喜歡較長的行寬。若是代碼主要由一個團隊維護,那這個問題就能達成一致,能夠把行長度從80增長到100個字符(更有效的作法是將行最大長度增長到99個字符),前提是註釋和文檔字符串依然已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())
(請參閱前面關於多行if-語句的討論,以得到關於這種多行with-語句縮進的進一步想法。)
另外一種相似狀況是使用assert語句。
確保在續行進行適當的縮進。
幾十年來,推薦的風格是在二元運算符以後中斷。可是這回影響可讀性,緣由有二:操做符通常分佈在屏幕上不一樣的列中,並且每一個運算符被移到了操做數的上一行。下面例子這個狀況就須要額外注意,那些變量是相加的,那些變量是相減的:
# 不推薦: 操做符離操做數太遠 income = (gross_wages + taxable_interest + (dividends - qualified_dividends) - ira_deduction - student_loan_interest)
爲了解決這種可讀性的問題,數學家和他們的出版商遵循了相反的約定。Donald Knuth在他的Computers and Typesetting系列中解釋了傳統規則:「儘管段落中的公式老是在二元運算符和關係以後中斷,顯示出來的公式老是要在二元運算符以前中斷」4。
遵循數學的傳統能產出更多可讀性高的代碼:
# 推薦:運算符和操做數很容易進行匹配 income = (gross_wages + taxable_interest + (dividends - qualified_dividends) - ira_deduction - student_loan_interest)
在Python代碼中,容許在二元運算符以前或以後中斷,只要本地的約定是一致的。對於新代碼,建議使用Knuth的樣式。
頂層函數和類的定義,先後用兩個空行隔開。
類裏的方法定義用一個空行隔開。
相關的功能組能夠用額外的空行(謹慎使用)隔開。一堆相關的單行代碼之間的空白行能夠省略(例如,一組虛擬實現 dummy implementations)。
在函數中使用空行來區分邏輯段(謹慎使用)。
Python接受control-L(即^L)換頁符做爲空格;許多工具把這些字符看成頁面分隔符,因此你能夠在文件中使用它們來分隔相關段落。請注意,一些編輯器和基於Web的代碼閱讀器可能沒法識別control-L爲換頁,將在其位置顯示另外一個字形。
Python核心發佈版本中的代碼老是以UTF-8格式編碼(或者在Python2中用ASCII編碼)。
使用ASCII(在Python2中)或UTF-8(在Python3中)編碼的文件不該具備編碼聲明。
在標準庫中,非默認的編碼應該只用於測試,或者當一個註釋或者文檔字符串須要說起一個包含內ASCII字符編碼的做者名字的時候;不然,使用\x,\u,\U , 或者 \N 進行轉義來包含非ASCII字符。
對於Python 3和更高版本,標準庫規定了如下策略(參見 PEP 3131):Python標準庫中的全部標識符必須使用ASCII標識符,並在可行的狀況下使用英語單詞(在許多狀況下,縮寫和技術術語是非英語的)。此外,字符串文字和註釋也必須是ASCII。惟一的例外是(a)測試非ASCII特徵的測試用例,以及(b)做者的名稱。做者的名字若是不使用拉丁字母拼寫,必須提供一個拉丁字母的音譯。
鼓勵具備全球受衆的開放源碼項目採起相似的政策。
導入一般在分開的行,例如:
推薦: import os import sys 不推薦: import sys, os
可是能夠這樣:
from subprocess import Popen, PIPE
你應該在每一組導入之間加入空行。
import mypkg.sibling from mypkg import sibling from mypkg.sibling import example
然而,顯示的指定相對導入路徑是使用絕對路徑的一個可接受的替代方案,特別是在處理使用絕對路徑導入沒必要要冗長的複雜包佈局時:
from . import sibling from .sibling import example
標準庫要避免使用複雜的包引入結構,而老是使用絕對路徑。
不該該使用隱式相對路徑導入,而且在Python 3中刪除了它。
from myclass import MyClass from foo.bar.yourclass import YourClass
若是上述的寫法致使名字的衝突,那麼這麼寫:
import myclass import foo.bar.yourclass
而後使用「myclass.MyClass」和「foo.bar.yourclass.YourClass」。
當以這種方式從新發布名稱時,如下關於公共和內部接口的準則仍然適用。
像 __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 os import 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, x No: 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: spam(1)
No: spam (1)
Yes: dct['key'] = lst[index] No: dct ['key'] = lst [index]
推薦:
x = 1 y = 2 long_variable = 3
不推薦:
x = 1 y = 2 long_variable = 3
推薦:
i = i + 1 submitted += 1 x = x*2 - 1 hypot2 = x*x + y*y c = (a+b) * (a-b)
不推薦:
i=i+1 submitted +=1 x = x * 2 - 1 hypot2 = x * x + y * y c = (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/for/while 放在同一行沒什麼問題,多行語句塊的狀況不要這樣用,一樣也要避免代碼行太長!
最好別這樣:
if foo == 'blah': do_blah_thing() for x in lst: total += x while t < 10: t = delay()
絕對別這樣:
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()
與代碼相矛盾的註釋比沒有註釋還糟,當代碼更改時,優先更新對應的註釋!
註釋應該是完整的句子。若是一個註釋是一個短語或句子,它的第一個單詞應該大寫,除非它是以小寫字母開頭的標識符(永遠不要改變標識符的大小寫!)。
若是註釋很短,結尾的句號能夠省略。塊註釋通常由完整句子的一個或多個段落組成,而且每句話結束有個句號。
在句尾結束的時候應該使用兩個空格。
當用英文書寫時,遵循Strunk and White (譯註:《Strunk and White, The Elements of Style》)的書寫風格。
在非英語國家的Python程序員,請使用英文寫註釋,除非你120%的確信你的代碼不會被使用其餘語言的人閱讀。
塊註釋一般適用於跟隨它們的某些(或所有)代碼,並縮進到與代碼相同的級別。塊註釋的每一行開頭使用一個#和一個空格(除非塊註釋內部縮進文本)。
塊註釋內部的段落經過只有一個#的空行分隔。
有節制地使用行內註釋。
行內註釋是與代碼語句同行的註釋。行內註釋和代碼至少要有兩個空格分隔。註釋由#和一個空格開始。
事實上,若是狀態明顯的話,行內註釋是沒必要要的,反而會分散注意力。好比說下面這樣就不須要:
x = x + 1 # Increment x
但有時,這樣作頗有用:
x = x + 1 # Compensate for border
編寫好的文檔說明(也叫「docstrings」)的約定在PEP 257中永恆不變。
"""Return a foobang Optional plotz says to frobnicate the bizbaz first. """
Python庫的命名規範很亂,歷來沒能作到徹底一致。可是目前有一些推薦的命名標準。新的模塊和包(包括第三方框架)應該用這套標準,但當一個已有庫採用了不一樣的風格,推薦保持內部一致性。
那些暴露給用戶的API接口的命名,應該遵循反映使用場景而不是實現的原則。
有許多不一樣的命名風格。這裏可以幫助你們識別正在使用什麼樣的命名風格,而不考慮他們爲何使用。
如下是常見的命名方式:
也有用惟一的短前綴把相關命名組織在一塊兒的方法。這在Python中不經常使用,但仍是提一下。好比,os.stat()函數中包含相似以st_mode,st_size,st_mtime這種傳統命名方式命名的變量。(這麼作是爲了與 POSIX 系統的調用一致,以幫助程序員熟悉它。)
X11庫的全部公共函數都加了前綴X。在Python裏面不必這麼作,由於屬性和方法在調用的時候都會用類名作前綴,函數名用模塊名作前綴。
另外,下面這種用前綴或結尾下劃線的特殊格式是被承認的(一般和一些約定相結合):
永遠不要使用字母‘l’(小寫的L),‘O’(大寫的O),或者‘I’(大寫的I)做爲單字符變量名。
在有些字體裏,這些字符沒法和數字0和1區分,若是想用‘l’,用‘L’代替。
模塊應該用簡短全小寫的名字,若是爲了提高可讀性,下劃線也是能夠用的。Python包名也應該使用簡短全小寫的名字,但不建議用下劃線。
當使用C或者C++編寫了一個依賴於提供高級(更面向對象)接口的Python模塊的擴展模塊,這個C/C++模塊須要一個下劃線前綴(例如:_socket)
類名通常使用首字母大寫的約定。
在接口被文檔化而且主要被用於調用的狀況下,可使用函數的命名風格代替。
注意,對於內置的變量命名有一個單獨的約定:大部份內置變量是單個單詞(或者兩個單詞鏈接在一塊兒),首字母大寫的命名法只用於異常名或者內部的常量。
由於異常通常都是類,全部類的命名方法在這裏也適用。然而,你須要在異常名後面加上「Error」後綴(若是異常確實是一個錯誤)。
(咱們但願這一類變量只在模塊內部使用。)約定和函數命名規則同樣。
經過 from M import * 導入的模塊應該使用all機制去防止內部的接口對外暴露,或者使用在全局變量前加下劃線的方式(代表這些全局變量是模塊內非公有)。
函數名應該小寫,若是想提升可讀性能夠用下劃線分隔。
大小寫混合僅在爲了兼容原來主要以大小寫混合風格的狀況下使用(好比 threading.py),保持向後兼容性。
始終要將 self 做爲實例方法的的第一個參數。
始終要將 cls 做爲類靜態方法的第一個參數。 若是函數的參數名和已有的關鍵詞衝突,在最後加單一下劃線比縮寫或隨意拼寫更好。所以 class_ 比 clss 更好。(也許最好用同義詞來避免這種衝突)
遵循這樣的函數命名規則:使用下劃線分隔小寫單詞以提升可讀性。
在非共有方法和實例變量前使用單下劃線。
經過雙下劃線前綴觸發Python的命名轉換規則來避免和子類的命名衝突。
Python經過類名對這些命名進行轉換:若是類 Foo 有一個叫 __a 的成員變量, 它沒法經過 Foo.__a 訪問。(執着的用戶能夠經過 Foo._Foo__a 訪問。)通常來講,前綴雙下劃線用來避免類中的屬性命名與子類衝突的狀況。
注意:關於__names的用法存在爭論(見下文)。
常量一般定義在模塊級,經過下劃線分隔的全大寫字母命名。例如: MAX_OVERFLOW 和 TOTAL。
始終要考慮到一個類的方法和實例變量(統稱:屬性)應該是共有仍是非共有。若是存在疑問,那就選非共有;由於將一個非共有變量轉爲共有比反過來更容易。
公共屬性是那些與類無關的客戶使用的屬性,並承諾避免向後不兼容的更改。非共有屬性是那些不打算讓第三方使用的屬性;你不須要承諾非共有屬性不會被修改或被刪除。
咱們不使用「私有(private)」這個說法,是由於在Python中目前尚未真正的私有屬性(爲了不大量沒必要要的常規工做)。
另外一種屬性做爲子類API的一部分(在其餘語言中一般被稱爲「protected」)。有些類是專爲繼承設計的,用來擴展或者修改類的一部分行爲。當設計這樣的類時,要謹慎決定哪些屬性時公開的,哪些是做爲子類的API,哪些只能在基類中使用。
貫徹這樣的思想,一下是一些讓代碼Pythonic的準則:
注意1:參考以前的類方法參數命名建議
注意1:屬性只在new-style類中起做用。
注意2:儘管功能方法對於相似緩存的負面影響比較小,但仍是要儘可能避免。
注意3:屬性標記會讓調用者認爲開銷(至關的)小,避免用屬性作開銷大的計算。
注意1:只有類名纔會整合進屬性名,若是子類的屬性名和類名和父類都相同,那麼你仍是會有命名衝突的問題。
注意2:命名轉換會在某些場景使用起來不太方便,例如調試,__getattr__()。然而命名轉換的算法有很好的文檔說明而且很好操做。
注意3:不是全部人都喜歡命名轉換。儘可能避免意外的名字衝突和潛在的高級調用。
任何向後兼容保證只適用於公共接口,所以,用戶清晰地區分公共接口和內部接口很是重要。
文檔化的接口被認爲是公開的,除非文檔明確聲明它們是臨時或內部接口,不受一般的向後兼容性保證。全部未記錄的接口都應該是內部的。
爲了更好地支持內省(introspection),模塊應該使用__all__屬性顯式地在它們的公共API中聲明名稱。將__all__設置爲空列表表示模塊沒有公共API。
即便經過__all__設置過,內部接口(包,模塊,類,方法,屬性或其餘名字)依然須要單個下劃線前綴。
若是一個命名空間(包,模塊,類)被認爲是內部的,那麼包含它的接口也應該被認爲是內部的。
導入的名稱應該始終被視做是一個實現的細節。其餘模塊必須不能間接訪問這樣的名稱,除非它是包含它的模塊中有明確的文檔說明的API,例如 os.path 或者是一個包裏從子模塊公開函數接口的 __init__ 模塊。
好比,不要依賴於在CPython中高效的內置字符鏈接語句 a += b 或者 a = a + b。這種優化甚至在CPython中都是脆弱的(它只適用於某些類型)而且沒有出如今不使用引用計數的實現中。在性能要求比較高的庫中,能夠種 」.join() 代替。這能夠確保字符關聯在不一樣的實現中均可以以線性時間發生。
另外,若是你在寫 if x 的時候,請注意你是否表達的意思是 if x is not None。舉個例子,當測試一個默認值爲None的變量或者參數是否被設置爲其餘值的時候。這個其餘值應該是在上下文中能成爲bool類型false的值。
推薦:
if foo is not None:
不推薦:
if not foo is None:
爲了最大程度減小這一過程的開銷, functools.total_ordering() 修飾符提供了用於生成缺乏的比較方法的工具。
PEP 207 指出Python實現了反射機制。所以,解析器會將 y > x 轉變爲 x < y,將 y >= x 轉變爲 x <= y,也會轉換x == y 和 x != y的參數。sort() 和 min()方法確保使用<操做符,max()使用>操做符。然而,最好仍是實現所有六個操做符,以避免在其餘地方出現衝突。
推薦:
def f(x): return 2*x
不推薦:
f = lambda x: 2*x
第一個形式意味着生成的函數對象的名稱是「f」而不是泛型「< lambda >」。這在回溯和字符串顯示的時候更有用。賦值語句的使用消除了lambda表達式優於顯式def表達式的惟一優點(即lambda表達式能夠內嵌到更大的表達式中)。
設計異常的等級,要基於撲捉異常代碼的須要,而不是異常拋出的位置。以編程的方式去回答「出了什麼問題?」,而不是隻是確認「出現了問題」(內置異常結構的例子參考 PEP 3151 )
類的命名規範適用於這裏,可是你須要添加一個「Error」的後綴到你的異常類,若是異常是一個Error的話。非本地流控制或者其餘形式的信號的非錯誤異常不須要特殊的後綴。
當故意替換一個內部異常時(Python 2 使用「raise X」, Python 3.3 以後 使用 「raise X from None」),確保相關的細節轉移到新的異常中(好比把AttributeError轉爲KeyError的時候保留屬性名,或者將原始異常信息的文本內容內嵌到新的異常中)。
第二種形式在Python3 的語法中不合法
使用小括號,意味着當異常裏的參數很是長,或者包含字符串格式化的時候,不須要使用換行符。
好比說:
try: import platform_specific_module except ImportError: platform_specific_module = None
若是隻有一個except: 塊將會捕獲到SystemExit和KeyboardInterrupt異常,這樣會很難經過Control-C中斷程序,並且會掩蓋掉其餘問題。若是你想捕獲全部指示程序出錯的異常,使用 except Exception: (只有except等價於 except BaseException:)。
兩種狀況不該該只使用‘excpet’塊:
try: process_data() except Exception as exc: raise DataProcessingFailedError(str(exc))
爲了不和原來基於逗號分隔的語法出現歧義,Python3只支持這一種語法。
推薦:
try: value = collection[key] except KeyError: return key_not_found(key) else: return handle_value(value)
不推薦:
try: # Too broad! return handle_value(collection[key]) except KeyError: # Will also catch KeyError raised by handle_value() return key_not_found(key)
推薦:
with conn.begin_transaction():
do_stuff_in_transaction(conn)
不推薦:
with conn:
do_stuff_in_transaction(conn)
第二個例子沒有提供任何信息去指明__enter__和__exit__方法在事務以後作出了關閉鏈接以外的其餘事情。這種狀況下,明確指明很是重要。
推薦:
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)
不推薦:
def foo(x): if x >= 0: return math.sqrt(x) def bar(x): if x < 0: return return math.sqrt(x)
字符串方法老是更快,而且和unicode字符串分享相同的API。若是須要兼容Python2.0以前的版本能夠不用考慮這個規則。
startswith()和endswith()更乾淨,出錯概率更小。好比:
推薦: if foo.startswith('bar'): 糟糕: if foo[:3] == 'bar':
正確: if isinstance(obj, int): 糟糕: if type(obj) is type(1):
當檢查一個對象是否爲string類型時,記住,它也有多是unicode string!在Python2中,str和unicode都有相同的基類:basestring,因此你能夠這樣:
if isinstance(obj, basestring):
注意,在Python3中,unicode和basestring都不存在了(只有str)而且bytes類型的對象再也不是string類型的一種(它是整數序列)
正確: if not seq: if seq: 糟糕: if len(seq): if not len(seq):
正確: if greeting: 糟糕: if greeting == True: 更糟: if greeting is True:
隨着PEP 484的引入,功能型註釋的風格規範有些變化。
# type: ignore
這會告訴檢查器忽略全部的註釋。(在 PEP 484中能夠找到從類型檢查器禁用投訴的更細粒度的方法。)
參考:https://blog.csdn.net/ratsniper/article/details/78954852