1. 程式人生 > >python開發規範(轉載)

python開發規範(轉載)

map 字符 internal oba range 只讀 命名約定 1.0 依次

轉載自http://www.cnblogs.com/wangcp-2014/p/4838952.html

目錄

  1. 代碼布局

    1.1 縮進

    1.2 表達式和語句中的空格

    1.3 行的最大長度

    1.4 空行

    1.5 編碼

  2. 語句

    2.1 標準頭部...

    2.2 導入(import)...

    2.3 賦值...

    2.4 分支和循環...

  3. 註釋

    3.1 註釋塊...

    3.2 行內註釋...

    3.3 文檔字符串...

    3.4 版本註記...

    3.5 模塊註釋...

    3.6 函數和方法註釋...

    3.7 類註釋...

  4. 命名約定...

    4.1 說明:命名約定...

    4.2 模塊名...

    4.4 類名...

    4.5 異常名...

    4.6 變量、常量、全局變量名...

    4.7 函數名...

    4.8 方法名和實例變量...

    4.9 特定的命名方式...

  5. 繼承的設計...

  6. 設計建議...

代碼布局

1.1 縮進
推薦以4個空格作為一個縮進層次。

1.2 表達式和語句中的空格

1.2.1 前導空格(縮進)

最流行的Python縮進方式是僅使用空格,其次是僅使用制表符。對於新的項目,應該僅使用空格而不是制表符。

1.2.2 非前導空格

非前導空格在Python代碼中沒有意義,但適當地加入非前導空格可以增進代碼可讀性:

(1)在二元算術、邏輯運算符前後加空格,如:

a = b + c
if a and b:
    pass

(2)在一元前綴運算符後不加空格,如:

if !flg:
    pass

(3)“:”用在行尾時前後皆不加空格,如分支、循環、函數和類定義語言;用在非行尾時後端加空格,如dict對象的定義:

d = {‘key‘: ‘value‘}

(4)括號(含圓括號、方括號和花括號)前後不加空格,如:

do_something(arg1, arg2)

(5)逗號後面加一個空格,前面不加空格。

1.3 行的最大長度
每行的最大長度不得超過80個字符的標準。超過80個字符的,建議使用以下方式將單個長行折疊成多個短行:

(1)為長變量名換一個短名,如:

錯誤寫法:

this.is.a.very.long.variable_name = this.is.another.long.variable_name

正確寫法:

variable_name1 = this.is.a.very.long.variable_name

variable_name2 = this.is.another.variable_name

variable_name1 = variable_name2

(2)在括號(包括圓括號、方括號和花括號)內的分隔符後換行,如:

示例:
class Edit(Base):

    def __init__(self, parent, width,

    font = FONT, color = BLACK, pos = POS, style = 0):  # 註意:此行與上一行保持同樣縮進
        pass

(3)在長行加入續行符強行斷行,斷行的位置應在操作符前,如:

if color == WHITE or color == BLACK 
or color == BLUE:  # 註意:換行與首行保持同樣的縮進(或均不縮進)

    do_something(color)

1.4 空行

輸入空行時,一般遵循以下原則:

(1)在import不同種類的模塊間加空行;

(2)頂層函數和類的定義之間加空行;

(3)在類與類的定義之間加空行;

(4)在函數與函數的定義之間加空行;

(5)在class定義行和其第一個方法定義之間加空行;

(6)在函數中的邏輯段落間加空行,即把相關的代碼緊湊寫在一起,作為一個邏輯段落,段落間以空行分隔。

1.5 編碼

所有的Python腳本文件都應在文件頭標上#-- coding:utf8 -- ;用於設置編輯器,默認保存為utf8格式:

#-*- coding:utf8 -*-

語句

2.1 標準頭部

一般情況下使用如下標準頭部語句:

#!/usr/bin/python

如果需要使用自定義的Python編譯環境,可使用類似如下的頭部語句:

#!/usr/bin/env python2.7

說明:該行語句的作用是幫助內核找到Python解釋器,但通常在Python導入模塊時被忽略;只有直接執行單個文件時,該語句才是必要的。

2.2 導入(import)

2.2.1 通常應該在單獨的行中導入(import),例如“正確寫法1”;若需要在一行中從一個模塊導入多個類,可參照“正確寫法2”:

錯誤寫法:

import sys, os

正確寫法1:

import sys

import os

正確寫法2:

from types import StringType, ListType

2.2.2 導入語句的位置及導入順序

通常將import語句放置在文件的頂部,僅在模塊註釋和文檔字符串之後,在模塊的全局變量和常量之前。導入語句應該有順序地成組安放:

(1)首先,導入標準庫(內置模塊);

(2)其次,導入第三方模塊(引用的第三方包);

(3)最後,導入自己開發的項目中的其他模塊;

在每組導入之間放置一個空行。

2.2.3. 導入類的方法

從一個包含類的模塊中導入類時,通常可以寫成這樣:

示例:

from MyClass import MyClass

from foo.bar.YourClass import YourClass

如果上述寫法導致了本地名字沖突,那麽就這樣寫:

示例:

import MyClass

import foo.bar.YourClass

然後使用MyClass.MyClass和foo.bar.YourClass.YourClass方式即可。

2.3 賦值

對於賦值語言,主要是不要做無謂的對齊,如:

錯誤寫法:

a        = 1

var      = 2

fn       = callback_function

正確寫法:

a = 1

var = 2

fn = callback_function

2.4 分支和循環
各種分支和循環語句不要寫成一行,如:

錯誤寫法:

if !flg: pass

for i in xrange(10): print i

正確寫法:

if !flg:

    pass

for i in xrange(10):

    print i

註釋

代碼修改時,始終優先更新註釋。註釋應該是完整的句子,如果註釋是一個短語或句子,首字母應該大寫,除非他是一個以小寫字母開頭的標識符(如果以中文註釋可忽略此要求)。

3.1 註釋塊

註釋塊通常用於跟隨著一些代碼並和這些代碼有著相同的縮進層次。註釋塊中每行均以“#”和一個空格開始。註釋塊內的段落間以僅含單個“#”的行分割。註釋塊上下方最好各有一空行。

3.2 行內註釋

行內註釋是和語句在同一行的註釋。行內註釋應該至少用兩個空格和語句分開,且應該以“#”和單個空格開始,如:

示例:

x = x + 1  # Increment x

如果語意很明了,那麽行內註釋則不必要。

3.3 文檔字符串

為所有公共模塊、函數、類和方法編寫文檔字符串。文檔字符串對非公開的方法不是必要的,但應該有一個註釋描述這個方法的作用。這個註釋應該在“def”行之後。

一定註意,多行文檔字符串結尾的"""應該單獨成行,例如:

示例:

"""Return a foobang

Optional plotz says to frobnicate the bizbaz first

"""

對單行的文檔字符串,結尾的"""在同一行也可以,例如:

"""Return a foobang"""

3.4 版本註記
版本註記可以參照如下示例代碼:

示例:

__version__ = "$Revision: 1.4 $"

這行應該包含在模塊的文檔字符串之後,所有代碼之前,上下用一個空行分割。

3.5 模塊註釋
每個模塊註釋都應該包含下列項,依次是:

(1)版權聲明;

(2)模塊註釋內容,包括模塊描述、模塊中的類和方法的描述、版本及維護信息等;

(3)作者聲明,標識文件的原作者;

示例:

# Copyright (C), 2010-2013, China Standard Software Co., Ltd.

"""

FileName: Test.py

Author: fei.liu

Version: 0.1

Date: 2013-02-27

Description: 用一行文字概述模塊或腳本,用句號結尾。

    ClassFoo: 一行概述該模塊中的類的用途。

    functionBar(): 一行概述該模塊中的函數的用途。

History: /* 歷史修改記錄 */

<Author>   <Date>   <Version>   <Desc>

fei.liu  2013-03-04   1.0      Release

"""

__authors__ = [

  ‘"John Smith" <[email protected]>‘,

  ‘"Joe Paranoid" <[email protected]>‘,

]

3.6 函數和方法註釋

任何函數或方法都需要一個文檔字符串,對於任何外部可訪問的函數或方法,文檔字符串尤為重要。

文檔字符串應該包含函數的作用,以及參數、輸入和輸出的詳細描述:

(1)Args:輸入參數的具體描述;如果參數要求特定的數據類型或者設置了參數的默認值,那麽應該在文檔字符串中明確說明;

(2)Returns:輸出(返回)數據的具體描述;

(3)Raises:應該列出該函數可能觸發的所有異常;

示例:

def fetch_bigtable_rows(big_table, keys, other_silly_variable=None):

    """取出表格中的多行內容

    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 rowto 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

3.7 類註釋
類定義下方必須有一個用於描述該類的文檔字符串(docString)。如果類中有公共屬性(Attributes),那麽文檔字符串中應該說明這些公共屬性的意義。

示例:

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."""

命名約定

4.1 說明:命名約定
禁止使用字符“l”、“O”或“I”作為單字符的變量名。在某些字體中無法將這些字符與數字1和0區分開。

4.2 模塊名
模塊名應該是不含下劃線的、簡短的、全小寫的名字;對於默認僅在包(Packages)內使用的模塊,可以加一個下劃線前綴,如:

示例:

module.py

_internal_module.py

4.4 類名
類名使用CapWords約定(單詞首字母大寫,不使用下劃線連接單詞,也不加入C、T等前綴);內部使用的類需要在名稱前加一個前導下劃線,如:

示例:

class ThisIsAClass(object):

pass

class _ThisIsAClass(object):

pass

4.5 異常名
異常名使用CapWords命名規則(單詞首字母大寫,不使用下劃線連接單詞)。

4.6 變量、常量、全局變量名
Python一般通過“from M import *”來從模塊中導入相關內容(變量、類、函數等),必須用一個下劃線作全局變量(內部函數或類)的前綴防止其被導出(exporting)。

4.6.1. 常量

常量名的所有字母均大寫,由下劃線連接各個單詞,如:

示例:

WHITE = 0XFFFFFF

THIS_IS_A_CONSTANT = 1

4.6.2. 變量

(1)變量名全部小寫,由下劃線連接各個單詞,如:

示例:

color = WHITE

this_is_a_variable = 1

(2)不論是類成員變量還是全局變量,均不使用m或g前綴。私有類成員使用單一下劃線前綴標識;

(3)變量名不應帶有類型信息,因為Python是動態類型語言;如iValue、names_list、dict_obj等都是不好的命名。

4.6.3. 全局變量

必須用一個下劃線作為全局變量的前綴防止其被導出。

4.7 函數名
函數名應該為小寫,可用下劃線風格單詞以增加可讀性。

4.8 方法名和實例變量
大體上和函數命名規則相同:通常使用小寫單詞,必要時用下劃線分隔增加可讀性。

如果是不打算對外公開的內部方法和實例,需要在名稱開頭使用一個前導下劃線。

使用兩個前導下劃線以表示類私有成員的名字。通常雙前導下劃線僅被用於避免含子類的類中的屬性名沖突。

4.9 特定的命名方式
主要是指__xxx__形式的系統保留字命名法。項目中也可以使用這種命名,它的意義在於這種形式的變量是只讀的,這種形式的類成員函數盡量不要重載。如:

示例:

class Base(object):

    def __init__(self, id, parent = None):

        self.__id__ = id

        self.__parent__ = parent

    def __message__(self, msgid):

        # ...

其中__id_、__parent__和__message__都采用了系統保留字命名法。

繼承的設計

始終要確定一個類中的方法和實例變量是否要被公開。通常,永遠不要將數據變量公開,除非你實現的本質上只是記錄,人們總是更喜歡為類提供一個函數的接口來實現數據變量的修改。

同樣,確定你的屬性是否應為私有的。私有和非私有的區別在於:前者永遠不會被用在一個派生類中,而後者可能會。你應該在大腦中就用繼承設計好了你的類:(1)私有屬性必須有兩個前導下劃線,無後置下劃線;(2)非公有屬性必須有一個前導下劃線,無後置下劃線;(3)公共屬性沒有前導和後置下劃線,除非它們與保留字沖突,在此情況下,單個後置下劃線比前置或混亂的拼寫要好,例如:class_優於klass。

設計建議

單個元素(singletons)的比較,如None應該使用“is”或“is not”。當你本意是“if x is not None”時,對寫成“if x”要小心。例如當你測試一個默認為None的變量或參數是否被設置為其它值時,這個其它值也許在布爾上下文(Boolean context)中是False。

基於類的異常總是好過基於字符串的異常。模塊和包應該定義它們自己的域內特定的基異常類,基類應該是內建的Exception類的子類,還始終包含一個類的文檔字符串。例如:

示例:

#!/usr/bin/Python
class(Exception):

"""Base class for errors in the email package."""

MessageError

使用字符串方法(methods)代替字符串模塊,除非必須向後兼容Python 2.0以前的版本。字符串方法總是非常快,而且和unicode字符串共用同樣的API(應用程序接口),在檢查前綴或後綴時避免對字符串進行切片。用startswith()和endswith()代替,因為這樣出現錯誤的機率更小。例如:

錯誤寫法:

if foo[:3] == ‘bar‘:

正確寫法:

if foo.startswith(‘bar‘):

特殊情況下,如果你的代碼必須工作在Python 1.5.2,對象類型的比較應該始終用isinstance()代替直接比較類型,例如:

錯誤寫法:

if type(obj) is type(1):

正確寫法:

if isinstance(obj, int):

檢查一個對象是否是字符串時,謹記它也可能是unicode字符串!在Python 2.3中,str和unicode有公共的基類basestring,所以你可以這樣做:

if isinstance(obj, basestring):

在Python 2.2類型模塊為此定義了StringTypes類型,例如:

#!/usr/bin/Python

from types import StringTypes

if isinstance(obj, StringTypes):

對序列(字符串、列表、元組)而言,使用空列表是false這個事實,因此“if not seq”或“if seq”比“if len(seq)”或“if not len(seq)”好。書寫字符串文字時不要依賴於有意義的後置空格。這種後置空格在視覺上是不可辨別的,並且有些編輯器會將它們修整掉。不要用“==”來比較布爾型的值以確定是True或False(布爾型是Python2.3中新增的):

錯誤寫法:

if greeting == True:

正確寫法:

if greeting:

python開發規範(轉載)