作者:cedar(http://www.itdecent.cn/writer#/notebooks/28559629/notes/32344372)
Python風(fēng)格規(guī)范
不要在行尾加分號(hào),也不要用分號(hào)將兩條命令放在同一行。
-
每行不超過(guò)80個(gè)字符。
- 2.1 長(zhǎng)的導(dǎo)入模塊語(yǔ)句和注釋里的URL例外。
- 2.2 不使用反斜杠連接行。
- 2.3 Python會(huì)將圓括號(hào),中括號(hào)和花括號(hào)中的行隱式的連接起來(lái)。
- 2.4 在注釋中,將長(zhǎng)的URL放在一行上。
寧缺勿濫的使用括號(hào),除非是用于行連接,否則不要在返回語(yǔ)句或條件語(yǔ)句中使用括號(hào)。
用四個(gè)空格來(lái)縮進(jìn)代碼,不要使用tab,也不要tab和空格混用。對(duì)于行連接的情況,應(yīng)該要么垂直對(duì)齊換行的元素或者使用4空格的懸掛式縮進(jìn)(此時(shí)第一行不該有參數(shù))。
空行:頂級(jí)定義(函數(shù)或者類定義)之間空兩行,方法定義之間空一行。
-
空格:按照標(biāo)準(zhǔn)的排版規(guī)范來(lái)使用標(biāo)點(diǎn)兩邊的空格。
- 6.1 括號(hào)內(nèi)不要有空格。
- 6.2 不要在逗號(hào),分號(hào),冒號(hào)前邊加空格,但應(yīng)該在后面加
- 6.3 參數(shù)列表,索引或切片的左括號(hào)前不應(yīng)加空格
- 6.4 在二元操作符兩邊都加上一個(gè)空格,比如賦值(=),比較(==,<,>,!=,<>,<=,>=,in,not in,is,is not),布爾(and,or,not)。至于算術(shù)操作符兩邊的空格該如何使用, 需要你自己好好判斷。 不過(guò)兩側(cè)務(wù)必要保持一致。
- 6.5 當(dāng)’=’用于指示關(guān)鍵字參數(shù)或默認(rèn)參數(shù)值時(shí),不要在其兩側(cè)使用空格。
- 6.6 不要用空格來(lái)垂直對(duì)齊多行間的標(biāo)記, 因?yàn)檫@會(huì)成為維護(hù)的負(fù)擔(dān)(適用于:,#,=等)。
Shebang:大部分.py文件不必以#!作為文件的開始。根據(jù) PEP-394,程序的main文件應(yīng)該以 #!/usr/bin/python2或者 #!/usr/bin/python3開始。
-
注釋:確保對(duì)模塊、函數(shù)、方法和行內(nèi)注釋使用正確的風(fēng)格。
- 8.1 文檔字符串:Python有一種獨(dú)一無(wú)二的的注釋方式,使用文檔字符串。文檔字符串是包, 模塊, 類或函數(shù)里的第一個(gè)語(yǔ)句。這些字符串可以通過(guò)對(duì)象的__doc__成員被自動(dòng)提取,并且被pydoc所用。(你可以在你的模塊上運(yùn)行pydoc試一把,看看它長(zhǎng)什么樣)。我們對(duì)文檔字符串的慣例是使用三重雙引號(hào)”“”( PEP-257 )。一個(gè)文檔字符串應(yīng)該這樣組織:首先是一行以句號(hào),問(wèn)號(hào)或驚嘆號(hào)結(jié)尾的概述(或者該文檔字符串單純只有一行)。接著是一個(gè)空行, 接著是文檔字符串剩下的部分,它應(yīng)該與文檔字符串的第一行的第一個(gè)引號(hào)對(duì)齊。下面有更多文檔字符串的格式化規(guī)范。
- 8.2 模塊:每個(gè)文件應(yīng)該包含一個(gè)許可樣板。根據(jù)項(xiàng)目使用的許可(例如,Apache 2.0,BSD,LGPL,GPL),選擇合適的樣板。
- 8.3 函數(shù)和方法:這里的函數(shù)包括函數(shù),方法,以及生成器。一個(gè)函數(shù)必須要有文檔字符串,文檔字符串應(yīng)該包含函數(shù)做什么,以及輸入和輸出的詳細(xì)描述。通常,不應(yīng)該描述怎么做,除非是一些復(fù)雜的算法。文檔字符串應(yīng)該提供足夠的信息,當(dāng)別人編寫代碼調(diào)用該函數(shù)時(shí),他不需要看一行代碼,只要看文檔字符串就可以了。對(duì)于復(fù)雜的代碼, 在代碼旁邊加注釋會(huì)比使用文檔字符串更有意義。
- 8.4 Args:列出每個(gè)參數(shù)的名字,并在名字后使用一個(gè)冒號(hào)和一個(gè)空格,分隔對(duì)該參數(shù)的描述。如果描述太長(zhǎng)超過(guò)了單行80字符,使用2或者4個(gè)空格的懸掛縮進(jìn)(與文件其他部分保持一致)。描述應(yīng)該包括所需的類型和含義。如果一個(gè)函數(shù)接受*foo(可變長(zhǎng)度參數(shù)列表)或者**bar (任意關(guān)鍵字參數(shù)),應(yīng)該詳細(xì)列出*foo和**bar。
- 8.5 Returns(或者Yields:用于生成器):描述返回值的類型和語(yǔ)義。如果函數(shù)返回None,這一部分可以省略。
- 8.6 Raises:列出與接口有關(guān)的所有異常。
- 8.7 類:類應(yīng)該在其定義下有一個(gè)用于描述該類的文檔字符串。如果你的類有公共屬性(Attributes),那么文檔中應(yīng)該有一個(gè)屬性(Attributes)段。并且應(yīng)該遵守和函數(shù)參數(shù)相同的格式。
- 8.8 塊注釋和行注釋:最需要寫注釋的是代碼中那些技巧性的部分。如果你在下次代碼審查的時(shí)候必須解釋一下,那么你應(yīng)該現(xiàn)在就給它寫注釋。對(duì)于復(fù)雜的操作,應(yīng)該在其操作開始前寫上若干行注釋。對(duì)于不是一目了然的代碼,應(yīng)在其行尾添加注釋。為了提高可讀性,注釋應(yīng)該至少離開代碼2個(gè)空格。
類 :如果一個(gè)類不繼承自其它類,就顯式的從object繼承。嵌套類也一樣。繼承自 object 是為了使屬性(properties)正常工作,并且這樣可以保護(hù)你的代碼,使其不受 PEP-3000 的一個(gè)特殊的潛在不兼容性影響。這樣做也定義了一些特殊的方法,這些方法實(shí)現(xiàn)了對(duì)象的默認(rèn)語(yǔ)義,包括 __new__,__init__,__delattr__,__getattribute__,__setattr__,__hash__,__repr__,and __str__ 。
-
字符串:
- 10.1 避免在循環(huán)中用+和+=操作符來(lái)累加字符串。由于字符串是不可變的,這樣做會(huì)創(chuàng)建不必要的臨時(shí)對(duì)象,并且導(dǎo)致二次方而不是線性的運(yùn)行時(shí)間。作為替代方案,你可以將每個(gè)子串加入列表,然后在循環(huán)結(jié)束后用 .join 連接列表。(也可以將每個(gè)子串寫入一個(gè) cStringIO.StringIO 緩存中。)
- 10.2 在同一個(gè)文件中,保持使用字符串引號(hào)的一致性。使用單引號(hào)’或者雙引號(hào)”之一用以引用字符串,并在同一文件中沿用。在字符串內(nèi)可以使用另外一種引號(hào),以避免在字符串中使用。GPyLint已經(jīng)加入了這一檢查。
- 10.3 為多行字符串使用三重雙引號(hào)”“”而非三重單引號(hào)’‘’。當(dāng)且僅當(dāng)項(xiàng)目中使用單引號(hào)’來(lái)引用字符串時(shí),才可能會(huì)使用三重’‘’為非文檔字符串的多行字符串來(lái)標(biāo)識(shí)引用。 文檔字符串必須使用三重雙引號(hào)”“”。不過(guò)要注意,通常用隱式行連接更清晰,因?yàn)槎嘈凶址c程序其他部分的縮進(jìn)方式不一致。
文件和sockets:在文件和sockets結(jié)束時(shí),顯式的關(guān)閉它。推薦使用 “with”語(yǔ)句 以管理文件。對(duì)于不支持使用”with”語(yǔ)句的類似文件的對(duì)象,使用 contextlib.closing()。
TODO注釋:為臨時(shí)代碼使用TODO注釋,它是一種短期解決方案。
-
導(dǎo)入格式:每個(gè)導(dǎo)入應(yīng)該獨(dú)占一行。導(dǎo)入總應(yīng)該放在文件頂部,位于模塊注釋和文檔字符串之后,模塊全局變量和常量之前。導(dǎo)入應(yīng)該按照從最通用到最不通用的順序分組。
- a. 標(biāo)準(zhǔn)庫(kù)導(dǎo)入
- b. 第三方庫(kù)導(dǎo)入
- c. 應(yīng)用程序指定導(dǎo)入
- d. 每種分組中,應(yīng)該根據(jù)每個(gè)模塊的完整包路徑按字典序排序,忽略大小寫。
語(yǔ)句:通常每個(gè)語(yǔ)句應(yīng)該獨(dú)占一行。
訪問(wèn)控制:在Python中,對(duì)于瑣碎又不太重要的訪問(wèn)函數(shù),你應(yīng)該直接使用公有變量來(lái)取代它們,這樣可以避免額外的函數(shù)調(diào)用開銷。當(dāng)添加更多功能時(shí),你可以用屬性(property)來(lái)保持語(yǔ)法的一致性。如果訪問(wèn)更復(fù)雜,或者變量的訪問(wèn)開銷很顯著,那么你應(yīng)該使用像 get_foo() 和 set_foo() 這樣的函數(shù)調(diào)用。如果之前的代碼行為允許通過(guò)屬性(property)訪問(wèn),那么就不要將新的訪問(wèn)函數(shù)與屬性綁定。
-
命名:
- 16.1 應(yīng)該避免的名稱:?jiǎn)巫址Q,除了計(jì)數(shù)器和迭代器;包/模塊名中的連字符(-);雙下劃線開頭并結(jié)尾的名稱(Python保留, 例如__init__)。
- 16.2 命名約定:所謂”內(nèi)部(Internal)”表示僅模塊內(nèi)可用,或者,在類內(nèi)是保護(hù)或私有的;用單下劃線(_)開頭表示模塊變量或函數(shù)是protected的(使用import * from時(shí)不會(huì)包含)。
用雙下劃線(__)開頭的實(shí)例變量或方法表示類內(nèi)私有。將相關(guān)的類和頂級(jí)函數(shù)放在同一個(gè)模塊里。不像Java,沒必要限制一個(gè)類一個(gè)模塊。對(duì)類名使用大寫字母開頭的單詞(如CapWords,即Pascal風(fēng)格),但是模塊名應(yīng)該用小寫加下劃線的方式(如lower_with_under.py)。盡管已經(jīng)有很多現(xiàn)存的模塊使用類似于CapWords.py這樣的命名,但現(xiàn)在已經(jīng)不鼓勵(lì)這樣做,因?yàn)槿绻K名碰巧和類名一致, 這會(huì)讓人困擾。
Main:即使是一個(gè)打算被用作腳本的文件,也應(yīng)該是可導(dǎo)入的。并且簡(jiǎn)單的導(dǎo)入不應(yīng)該導(dǎo)致這個(gè)腳本的主功能(main functionality)被執(zhí)行,這是一種副作用。主功能應(yīng)該放在一個(gè)main()函數(shù)中。
引用參考:http://zh-google-styleguide.readthedocs.io/en/latest/google-python-styleguide/python_style_rules/