Python代碼風(fēng)格檢查與格式化

Python代碼風(fēng)格檢查與格式化

參考資料

依賴(lài)包安裝

pip install flake8 -i https://pypi.douban.com/simple  # 代碼檢查工具
pip install yapf -i https://pypi.douban.com/simple  # Google開(kāi)源的Python格式化工具

常用規(guī)則

  • 代碼頭部:程序的main文件應(yīng)該以#!/usr/bin/python2或者#!/usr/bin/python3開(kāi)始。#!先用于幫助內(nèi)核找到Python解釋器, 但是在導(dǎo)入模塊時(shí), 將會(huì)被忽略. 因此只有被直接執(zhí)行的文件中才有必要加入#!.

  • 一行代碼過(guò)長(zhǎng)時(shí)的處理

    • 括號(hào)內(nèi)的參數(shù)很多的時(shí)候, 為了滿(mǎn)足每一行的字符不超過(guò)79個(gè)字符,
    • 需要將參數(shù)換行編寫(xiě), 這個(gè)時(shí)候換行的參數(shù)應(yīng)該與上一行的括號(hào)對(duì)齊.
    • 或者將所有參數(shù)換行編寫(xiě), 此時(shí)第一行不能有參數(shù),
    • 即第一行的最后一個(gè)字符一定要是(, 換行后需要有一個(gè)縮進(jìn).
    • 類(lèi)似的規(guī)則也用在[], {}上.

命名規(guī)則

  • 應(yīng)避免的命名
單字符名稱(chēng), 除了計(jì)數(shù)器和迭代器.
包/模塊名中的連字符(-)
雙下劃線(xiàn)開(kāi)頭并結(jié)尾的名稱(chēng)(Python保留, 例如__init__)
  • 命名約定
所謂"內(nèi)部(Internal)"表示僅模塊內(nèi)可用, 或者, 在類(lèi)內(nèi)是保護(hù)或私有的.
用單下劃線(xiàn)(_)開(kāi)頭表示模塊變量或函數(shù)是protected的(使用import * from時(shí)不會(huì)包含).
用雙下劃線(xiàn)(__)開(kāi)頭的實(shí)例變量或方法表示類(lèi)內(nèi)私有.
將相關(guān)的類(lèi)和頂級(jí)函數(shù)放在同一個(gè)模塊里. 不像Java, 沒(méi)必要限制一個(gè)類(lèi)一個(gè)模塊.
對(duì)類(lèi)名使用大寫(xiě)字母開(kāi)頭的單詞(如CapWords, 即Pascal風(fēng)格), 但是模塊名應(yīng)該用小寫(xiě)加下劃線(xiàn)的方式(如lower_with_under.py). 盡管已經(jīng)有很多現(xiàn)存的模塊使用類(lèi)似于CapWords.py這樣的命名, 但現(xiàn)在已經(jīng)不鼓勵(lì)這樣做, 因?yàn)槿绻K名碰巧和類(lèi)名一致, 這會(huì)讓人困擾.
  • Python之父Guido推薦的規(guī)范
Type Public Internal
Modules lower_with_under _lower_with_under
Packages lower_with_under -
Classes CapWords _CapWords
Exceptions CapWords -
Functions lower_with_under() _lower_with_under()
Global/Class Constants CAPS_WITH_UNDER _CAPS_WITH_UNDER
Global/Class Variables lower_with_under _lower_with_under
Instance Variables lower_with_under _lower_with_under (protected) or __lower_with_under (private)
Method Names lower_with_under() _lower_with_under() (protected) or __lower_with_under() (private)
Function/Method Parameters lower_with_under -
Local Variables lower_with_under -

導(dǎo)入格式

  • 每個(gè)導(dǎo)入應(yīng)該獨(dú)占一行
  • 導(dǎo)入總應(yīng)該放在文件頂部, 位于模塊注釋和文檔字符串之后, 模塊全局變量和常量之前. 導(dǎo)入應(yīng)該按照從最通用到最不通用的順序分組:
標(biāo)準(zhǔn)庫(kù)導(dǎo)入
第三方庫(kù)導(dǎo)入
應(yīng)用程序指定導(dǎo)入
  • 每種分組中, 應(yīng)該根據(jù)每個(gè)模塊的完整包路徑按字典序排序, 忽略大小寫(xiě)
import foo
from foo import bar
from foo.bar import baz
from foo.bar import Quux
from Foob import ar

函數(shù)定義

  • 文檔字符串應(yīng)該包含函數(shù)做什么, 以及輸入和輸出的詳細(xì)描述. 通常, 不應(yīng)該描述"怎么做", 除非是一些復(fù)雜的算法. 文檔字符串應(yīng)該提供足夠的信息, 當(dāng)別人編寫(xiě)代碼調(diào)用該函數(shù)時(shí), 他不需要看一行代碼, 只要看文檔字符串就可以了. 對(duì)于復(fù)雜的代碼, 在代碼旁邊加注釋會(huì)比使用文檔字符串更有意義.
  • 函數(shù)和方法注釋說(shuō)明。如果一個(gè)函數(shù)接受*foo(可變長(zhǎng)度參數(shù)列表)或者**bar (任意關(guān)鍵字參數(shù)), 應(yīng)該詳細(xì)列出*foo**bar
  • 規(guī)則:
Args:
列出每個(gè)參數(shù)的名字, 并在名字后使用一個(gè)冒號(hào)和一個(gè)空格, 分隔對(duì)該參數(shù)的描述.如果描述太長(zhǎng)超過(guò)了單行80字符,使用2或者4個(gè)空格的懸掛縮進(jìn)(與文件其他部分保持一致). 描述應(yīng)該包括所需的類(lèi)型和含義. 如果一個(gè)函數(shù)接受*foo(可變長(zhǎng)度參數(shù)列表)或者**bar (任意關(guān)鍵字參數(shù)), 應(yīng)該詳細(xì)列出*foo和**bar.
Returns: (或者 Yields: 用于生成器)
描述返回值的類(lèi)型和語(yǔ)義. 如果函數(shù)返回None, 這一部分可以省略.
Raises:
列出與接口有關(guān)的所有異常.
  • 示例:
def fetch_bigtable_rows(big_table, keys, other_silly_variable=None):
    """Fetches rows from a Bigtable.

    Retrieves rows pertaining to the given keys from the Table instance
    represented by big_table.  Silly things may happen if
    other_silly_variable is not None.

    Args:
        big_table: An open Bigtable Table instance.
        keys: A sequence of strings representing the key of each table row
            to fetch.
        other_silly_variable: Another optional variable, that has a much
            longer name than the other args, and which does nothing.

    Returns:
        A dict mapping keys to the corresponding table row data
        fetched. Each row is represented as a tuple of strings. For
        example:

        {'Serak': ('Rigel VII', 'Preparer'),
         'Zim': ('Irk', 'Invader'),
         'Lrrr': ('Omicron Persei 8', 'Emperor')}

        If a key from the keys argument is missing from the dictionary,
        then that row was not found in the table.

    Raises:
        IOError: An error occurred accessing the bigtable.Table object.
    """
    pass

類(lèi)定義

  • 類(lèi)應(yīng)該在其定義下有一個(gè)用于描述該類(lèi)的文檔字符串. 如果你的類(lèi)有公共屬性(Attributes), 那么文檔中應(yīng)該有一個(gè)屬性(Attributes)段. 并且應(yīng)該遵守和函數(shù)參數(shù)相同的格式.
class SampleClass(object):
    """Summary of class here.

    Longer class information....
    Longer class information....

    Attributes:
        likes_spam: A boolean indicating if we like SPAM or not.
        eggs: An integer count of the eggs we have laid.
    """

    def __init__(self, likes_spam=False):
        """Inits SampleClass with blah."""
        self.likes_spam = likes_spam
        self.eggs = 0

    def public_method(self):
        """Performs operation blah."""
  • 如果一個(gè)類(lèi)不繼承自其它類(lèi), 就顯式的從object繼承
class SampleClass(object):
    pass
  • 如果訪(fǎng)問(wèn)更復(fù)雜, 或者變量的訪(fǎng)問(wèn)開(kāi)銷(xiāo)很顯著, 那么你應(yīng)該使用像 get_foo()set_foo() 這樣的函數(shù)調(diào)用. 如果之前的代碼行為允許通過(guò)屬性(property)訪(fǎng)問(wèn) , 那么就不要將新的訪(fǎng)問(wèn)函數(shù)與屬性綁定. 這樣, 任何試圖通過(guò)老方法訪(fǎng)問(wèn)變量的代碼就沒(méi)法運(yùn)行, 使用者也就會(huì)意識(shí)到復(fù)雜性發(fā)生了變化.

注釋

  • TODO:TODO注釋?xiě)?yīng)該在所有開(kāi)頭處包含"TODO"字符串, 緊跟著是用括號(hào)括起來(lái)的你的名字, email地址或其它標(biāo)識(shí)符. 然后是一個(gè)可選的冒號(hào). 接著必須有一行注釋, 解釋要做什么.
# TODO(kl@gmail.com): Use a "*" here for string repetition.
# TODO(Zeke) Change this to use relations.
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容