閑話:今天去找實驗室老師&學長第一次面談,問學長說有沒有以前的代碼能用的,然后學長就開始瘋狂吐槽前面一個搞這個項目的人代碼風格如何如何不好。想起來高中的時候寫代碼老是被人吐槽,於是問了下有什么代碼規范。第一次知道原來真的是有官方標准存在的,回來立馬查了一下。PEP8 Style Guide for Python Code 原網站 https://www.python.org/dev/peps/pep-0008/ 下面是筆記。
1 Introduction
Guido 的核心思想是:對於代碼而言,相比於寫,它更多是被用來讀的。這個指導旨在使Python代碼更易讀,且具有更強的協調性。
2 A Foolish Consistency is the Hobgoblin of Little Minds
然而有些情況下遵從guide不是很合適,要學會變通,查看其他人的代碼,並且不要害怕提問
當遵從guideline的是會降低可讀性、降低繼承性/可移植性、使得代碼無法與環境中其他代碼兼容、需要和其他不符合這個guide的其他python版本代碼兼容的時候,記得變通。
3 Code lay-out
·使用四個空格縮進,python3不兼容tab與空格混用;
·每行不超過80個字符。為了保證代碼段可以自由左右移動,建議一行不超過72個字符。有些團隊會有大於80的行字符限制,但是注釋仍然應保持在72字符以內
·長的行需要換行的時候,使用Python自動連接括號(或者方括號、花括號)內的內容的功能,不要使用強制換行符。換行的時候注意內容的垂直對齊,增加一級縮進以防歧義或識別不明。在不能使用空格的時候才用\換行
·當if的條件很復雜的時候,在使用 “if (...”的形式可以形成自然的四格縮進,會導致歧義;有以下的解決方案——增加一行注釋來區分內容和條件;增加多是縮進來區分內容和條件
·多行內容結束時,右括號可以放在最后一行內容第一個字符的正下方或者是開始這個多行語句的正下方。
·在二元操作符之前換行會使代碼更整齊
·在class和一級函數上用兩個空行,類內的函數使用一個空行,可以用多的空行來區分不同塊的函數,簡單的程序間可以省略空行
·應該使用UTF-8(python3)或ASCII(python2)編碼,按此規范編碼的程序不需要聲明。非標准編碼方式應該只在測試需要的情況或者注釋中使用。
·在python3及以上的版本中,只使用ASCII編碼字符作為標識符(identifiers),並且盡量使用英文詞匯作為標識符。除了1)測試集中含有非ASCII字符,2)作者的姓名(不基於拉丁語系的字母必須給出拉丁文翻譯),這兩個情況之外,字符串和注釋也必須使用ASCII字符。
·import的時候不同的庫分開引用,但是可以將從同一個庫中引用的模塊合並寫。總是在文件開頭就進行引用——在注釋、文件信息之后,全局模塊、常量之前。
·import應按照以下順序分組(用空行隔開組):1)標准庫,2)相關的第三方庫,3)本地的庫或特殊引用
·建議精確引用以提升可讀性、穩定性。除非精確引用會導致本地變量名的沖突。避免在引用時使用通配符*
·模塊級別的“dunders”(例如__all__,__author__等)應該放在文件頭說明之后、引用之前。這個類型的賦值也應放在import之前。
4 String Quotes
固定一種字符串的符號,並在內容中出現歧義的時候用另外一種代替,避免使用\符號以增加可讀性。
5 Whitespace in Expressions and Statements
·括號兩側、冒號,分號之前、’不用空格
·關於切片的空格沒看懂,大體是要統一、可以看作二元操作符
·總是在 =(賦值), += ,-=,==,<,>,!=,<=,>=,in,not in, is,is not, and or not,->等二元操作符兩側加空格
·當有多級優先級運算的時候,在最低級的操作符兩側加空格
·在=表示變量默認值的時候 不用加空格
·不要在同一行里做多個操作
6 When to use trailing commas
https://www.python.org/dev/peps/pep-0008/#id29
7 Comments
·注釋應該是完整的句子,並且保證句首大寫(除非句首是個小寫的變量名),長句子要在句尾加句號,在句尾句號之后用兩個空格隔開。
·注釋塊:和被注釋的對象統一縮進等級。每一行以“# ”開頭,邊緣用一行“#”表示
·行內注釋:至少要空開兩格再開始寫,同樣以“# ”開頭
·文檔的注釋串:為所有public的模塊、函數、類、methods寫注釋。不是所有非public都要有注釋,但是你應該為它寫一個評論來說明功能,在def下面一行。注意,多行的注釋結束時的”””應該另起一行
8 Naming Conventions
python 的library是混亂的,所以永遠不能指望這部分能完全一致,下面有些推薦的命名標准。新寫的包應該遵循以下標准,已經寫好的就不管了。
overriding principle:使用當前API時可見的變量名應該反應其作用
Descriptive--Naming Styles:
保持統一的風格
使用首字母大寫的時候,縮寫單詞要全大寫——HTTPSeverError
不要自己發明這樣形式的名字:__haha__
Prescriptive--Name Conventions:
·不要使用小寫l,大寫O,大寫I作為單個字母變量名
·應該使用標准ASCLII編碼字符作為變量名
·module:短的、全小寫的名字。可以用下划線增加可讀性,但是不鼓勵。當C或C++模塊是更高級的時候,在開頭加一個下划線 標明
·Class:首字母大寫格式CapWords,可以使用函數的命名約定來代替在借口被記錄並主要用作可調用的情況。類內命名有多中形式——單個詞或者兩個詞連着寫,首字母大寫的情況只用於exception和constants
·Type variables:首字母大寫,並且簡寫。AnyStr,建議在covariant或vontravariant行為的時候使用“_co”,"_contra"后綴。例如:VT_co = TypeVar('VT_co', covariant=True)
·Exception:應該是類,所以用類的命名方式,但是應該加上“Error”后綴(如果是一個錯誤的話)
·Global Variable:假設只在一個模塊里面用。具有 from M import * 功能的模塊應該使用__all__機制來防止導出全局變量,或者使用之前的在前面加前綴的方式來防止這一點。
·Function:小寫,單詞用下划線隔開。混合形式只在之前使用過這樣的形式里使用來保持與之前的兼容。
·Function and method argument:總是在第一次出現instance methods的argument時使用self;在第一次出現class methods 的 argument的時候使用cls。在出現和保留字沖突的時候,在單詞后面加一個下划線比使用簡寫或者其他拼寫更好。
·Method names and instance variables:使用function的命名規則——小寫字母加下划線。僅在非public methods和instance variables的時候使用開頭下划線。為了防止和子類的沖突,在開頭使用雙下划線來激活python的命名 mangling規則(使用Foo.__a無法調用,而應該使用Foo._Foo__a)
·Constants:通常是在模塊里的常量,全大寫、用下划線隔開:MAX_OVERFLOW,TOTAL
·總是確定methods 和instance variables 是否全局可用,不確定的時候用non-public。全局變量是在那些和當前類不相關的用戶使用的。[這塊后面還有好多,暫時用不到,以后看]
Public and internal interfaces
9 Programming Recommendations
·程序需要在其他平台也可用:不要依賴Cpy的字符串加法 而是用join
·None值的判定總是使用 is或者 is not 而不是使用等於操作,然后在bool變量的時候可能會有歧義——if x 表示 if x is not None
· 使用 is not 而不是 not ... is
·在 implement 比較順序函數的時候,同時implement六個操作(__eq__,__ne__,__lt__,__le__,__gt__,__ge__)而不是僅包含部分操作符
·總是使用 def 而不是lambda表達式賦值來表示一個直接的函數
·Exception 和BaseException
·raise
·except
·system error
·try
·with
·保證函數要么所有情況都有返回值要么都沒有
·使用string method 而不是string modulw
·使用 ''.startswith()和''.endswith()而不是string切片來檢查前后綴,其他的比較應該用isinstance()而不是直接比較type()函數值
·在判斷序列是否為空的時候,使用if seq ,而不是 if len(seq)
·不要依賴字符串結尾的空格
·不要用 True來判斷boolean值:
yes: if greeting
no: if greeting == Ture
Worse: if greeting is True
·Function Annotations
Py3用PEP 484里的相關內容
Reference
https://www.python.org/dev/peps/pep-0008/
