Python編碼規(guī)范

--<<PEP 0008 -- Style Guide for Python Code>>

令人討厭的小人物身上有著愚蠢的一致性

--(A Foolish Consistency is the Hobgoblin of Little Minds)

  • 代碼的統(tǒng)一是為了增強(qiáng)可讀性官卡,因此一個(gè)項(xiàng)目中代碼風(fēng)格的統(tǒng)一很重要隙姿;

  • 知道什么時(shí)候統(tǒng)一,什么時(shí)候不統(tǒng)一熙参,觀察不同的樣例,選出自己喜歡的福也,多質(zhì)疑局骤,多探索;

  • 不打破向后兼容的特性正符合PEP8的特性暴凑;

    打破一條既定規(guī)則的幾個(gè)好理由:

  • 當(dāng)應(yīng)用這條規(guī)則時(shí)將導(dǎo)致代碼可讀性下降峦甩,即便對(duì)某人來(lái)說(shuō),他已經(jīng)習(xí)慣于按這條規(guī)則來(lái)閱讀代碼了现喳。

  • 為了和周圍的代碼保持一致而打破規(guī)則 (也許是歷史原因) -- 雖然這也是個(gè)清除其他人代碼混亂的好機(jī)會(huì) (在真正的 XP 風(fēng)格中)凯傲。

  • 因?yàn)闅埩魡?wèn)題的代碼先于引入準(zhǔn)則而單程,而此時(shí)沒(méi)有其他理由來(lái)修改這些代碼嗦篱;

  • 當(dāng)代碼需要保持與舊版本的Python的功能兼容,但代碼卻是風(fēng)格指南不支持推薦的泣洞。

代碼布局

--(Code lay-out)

(縮進(jìn))Indentation

<pre><code>Yes(正確):

Aligned with opening delimiter.

foo = long_function_name(var_one, var_two,
var_three, var_four)

More indentation included to distinguish this from the rest.

def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)

Hanging indents should add a level.

foo = long_function_name(
var_one, var_two,
var_three, var_four)

No(錯(cuò)誤):

Arguments on first line forbidden when not using vertical alignment.

foo = long_function_name(var_one, var_two,
var_three, var_four)

Further indentation required as indentation is not distinguishable.

def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)`</code></pre>

對(duì)連續(xù)的行來(lái)說(shuō),空格4是可選的

--(The 4-space rule is optional for continuation lines.)

<pre><code>Optional:

Hanging indents may be indented to other than 4 spaces.(懸掛縮進(jìn)不同于空格4)

foo = long_function_name(
var_one, var_two,
var_three, var_four)

當(dāng)條件語(yǔ)句 if -statement 太長(zhǎng)而需要多行顯示的時(shí)候, 標(biāo)記組合關(guān)鍵默色、增加一個(gè)空格、增加半開(kāi)始括號(hào)狮腿、每行添加4-空格是很有價(jià)值的腿宰。這樣可
能會(huì)產(chǎn)生if -statement中那些前面同樣添加了4-空格的嵌套式語(yǔ)句的視覺(jué)沖突。PEP的做法沒(méi)有很好的解決上述存在的嵌套語(yǔ)句的視覺(jué)混淆問(wèn)題缘厢,
下面的樣例中給出了一些可接受的做法吃度,當(dāng)然不僅限于此:

No extra indentation.

if (this_is_one_thing and
that_is_another_thing):
do_something()

Add a comment, which will provide some distinction in editors

supporting syntax highlighting.

if (this_is_one_thing and
that_is_another_thing):
# Since both conditions are true, we can frobnicate.
do_something()

Add some extra indentation on the conditional continuation line.

if (this_is_one_thing
and that_is_another_thing):
do_something()

閉合的另一半括號(hào)/中括號(hào)/大括號(hào),可以與列表中最后一行第一個(gè)非空格元素對(duì)齊贴硫,如下:

my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)

也可以與構(gòu)造列表的第一行的元素的第一個(gè)字符對(duì)齊, 如下:

my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)</code></pre>

(Tabs還是空格)Tabs or Spaces?

--空格space是縮進(jìn)(indentation)的首選;

--Tabs椿每,一般如果一開(kāi)始就試圖用tab鍵來(lái)實(shí)現(xiàn)縮進(jìn),后面才會(huì)繼續(xù)用tab來(lái)唯一的實(shí)現(xiàn)縮進(jìn);

--python3不允許混合使用spacetab;

--python2傾向于將混合使用的spacetab轉(zhuǎn)換為唯一的spqce;

最大代碼行長(zhǎng)度

--(Maximum Line Length)

--限制每行字符的最大長(zhǎng)度為79個(gè)字符

--對(duì)于結(jié)構(gòu)限制較少的文本字符串和注釋英遭,限定長(zhǎng)度為72個(gè)字符

--可以根據(jù)開(kāi)發(fā)團(tuán)隊(duì)適時(shí)需求间护,修改限定長(zhǎng)度在80-100之間,但是文本字符串和注釋還是72比較好

--可以使用轉(zhuǎn)義字符\拼接挖诸,用例如下:
<pre><code>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())

class Rectangle(Blob):

def __init__(self, width, height,
             color='black', emphasis=None, highlight=0):
    if (width == 0 and height == 0 and
            color == 'red' and emphasis == 'strong' or
            highlight > 100):
        raise ValueError("sorry, you lose")
    if width == 0 and height == 0 and (color == 'red' or
                                       emphasis is None):
        raise ValueError("I don't think so -- values are %s, %s" %
                         (width, height))
    Blob.__init__(self, width, height,
                  color, emphasis, highlight)</code></pre>

空行

--(Blank Lines)

--頂層函數(shù)和類的定義之間要空兩行汁尺;

--類中的方法定義間要空一行;

--額外的空行可被用于 (保守的 (sparingly)) 分割相關(guān)函數(shù)群 (groups of related functions)多律。在一組相關(guān)的單句 (related one-liners) 中間可以省略空行 (例如一組啞元 (dummy implementations))痴突;

--在函數(shù)中使用空行時(shí),請(qǐng)謹(jǐn)慎的用于表示一個(gè)邏輯段落 (logical sections)狼荞;

--Python 接受 contrl-L (即 ^L) 換頁(yè)符作為空白符 (whitespace)辽装;許多工具視這些 字符為分頁(yè)符 (page separators),因此在你的文件中相味,可以用它們來(lái)為相關(guān)片段 (sections) 分頁(yè);

源文件編碼

--(Source File Encoding)

--Python 核心發(fā)布中的代碼應(yīng)該始終使用 ASCII 或 Latin-1 編碼(又名ISO-8859-1)拾积。

--使用ASCII的文件不必有譯碼 cookie (coding cookie)。 Latin-1 僅當(dāng)注釋或文檔字 符串涉及作者名字需要 Latin-1 時(shí)才被使用;另外使用 \x 轉(zhuǎn)義字符是在字符串中包 含非 ASCII 數(shù)據(jù)的首選方法殷勘。

導(dǎo)入

--(imports)

  • -通常應(yīng)該在單獨(dú)的行中導(dǎo)入此再,例如:
    <pre><code>Yes:
    import os
    import sys
    No:
    import sys, os
    但是這樣也是可以的:
    from subprocess import Popen, PIPE
    -- Imports 通常被放置在文件的頂部,僅在模塊注釋和文檔字符串之后玲销,在模塊的全局變量和常量之前输拇。
    Imports應(yīng)該按照如下順序成組安放:
    1 標(biāo)準(zhǔn)庫(kù)的導(dǎo)入
    2 相關(guān)的第三方包的導(dǎo)入
    3 本地應(yīng)用/庫(kù)的特定導(dǎo)入
    你應(yīng)該在每組導(dǎo)入之間放置一個(gè)空行。
    把任何相關(guān) all 說(shuō)明的放在 imports 之后贤斜。
    對(duì)于內(nèi)部包的導(dǎo)入是非常不推薦使用相對(duì)導(dǎo)入的策吠。對(duì)所有導(dǎo)入總是使用包的絕對(duì)路徑。即使現(xiàn)在 PEP 328 7 在 Python 2.5 中被完整實(shí)現(xiàn)了瘩绒,
    其 explicit relative imports 的風(fēng)格也是不推薦的猴抹。絕對(duì)導(dǎo)入能更好的移植 (portable),通 常也更易讀;
    從一個(gè)包含類的模塊中導(dǎo)入類時(shí)锁荔,通丑案可以寫(xiě)成這樣:
    from myclass import MyClass
    from foo.bar.yourclass import YourClass
    如果這樣寫(xiě)導(dǎo)致了本地名字沖突,那么就這樣寫(xiě):
    import myclass import foo.bar.yourclass
    并使用 "myclass.MyClass" and "foo.bar.yourclass.YourClass"</code></pre>

無(wú)傷大雅的小問(wèn)題

--(Pet Peeves)

  • 在以下情況盡量避免多余的空格:

    在括號(hào)阳堕,中括號(hào)跋理,大括號(hào)內(nèi).

    <pre><code>Yes: spam(ham[1], {eggs: 2})
    No: spam( ham[ 1 ], { eggs: 2 } )</code></pre>

    在逗號(hào),分號(hào)恬总,句號(hào)前:

    <pre><code>Yes: if x == 4: print x, y; x, y = y, x
    No: if x == 4 : print x , y ; x , y = y , x</code></pre>

    當(dāng)分片的時(shí)候前普,在[]中,冒號(hào)相當(dāng)于一個(gè)二目運(yùn)算符壹堰,而且具有在任一側(cè)等價(jià)的位置拭卿,所有冒號(hào)必須有相同分量的空格,當(dāng)然贱纠,當(dāng)分片中分號(hào)兩側(cè)的參數(shù)缺省時(shí)峻厚,空格也缺省

    <pre><code>Yes:

    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]
    No:

    ham[lower + offset:upper + offset]
    ham[1: 9], ham[1 :9], ham[1:9 :3]
    ham[lower : : upper]
    ham[ : upper]</code></pre>

    在左括號(hào)與函數(shù)名間

    <pre><code>Yes: spam(1)
    No: spam (1)</code></pre>

    在左中括號(hào)與參數(shù)名間:

    <pre><code>Yes: dct['key'] = lst[index]
    No: dct ['key'] = lst [index]</code></pre>

    定義變量的時(shí)候,變量名與賦值操作符之間多于一個(gè)空格.

    <pre><code>Yes:

    x = 1
    y = 2
    long_variable = 3
    No:

    x = 1
    y = 2
    long_variable = 3</code></pre>

其他建議

--(Other Recommendations)

  • 始終在這些二元運(yùn)算符兩邊放置一個(gè)空格:

    assignment (=),
    augmented assignment (+=, -= etc.),
    comparisons (==, <, >, !=, <>, <=, >=, in, not in, is, is not),
    Booleans (and, or, not)

  • 在數(shù)學(xué)運(yùn)算符兩邊使用空格:

    <pre><code>Yes:
    i = i + 1 submitted += 1 x = x 2 - 1 hypot2 = x x + y y c = (a + b) (a - b)
    No:
    i=i+1 submitted +=1 x = x2 - 1 hypot2 = xx + y*y c = (a+b) (a-b)</code></pre>

  • 不要在用于指定關(guān)鍵字參數(shù) (keyword argument) 或默認(rèn)參數(shù)值的 '=' 號(hào)周圍使用空格并巍。

    <pre><code>Yes:
    def complex(real, imag=0.0):
    return magic(r=real, i=imag)
    No:
    def complex(real, imag = 0.0):
    return magic(r = real, i = imag)</code></pre>

  • 復(fù)合語(yǔ)句 (Compound statements) (多條語(yǔ)句寫(xiě)在同一行) 一般不推薦目木。

    <pre><code>Yes:
    if foo == 'blah':
    do_blah_thing()
    do_one()
    do_two()
    do_three()

    Rather not:
    if foo == 'blah': do_blah_thing() do_one(); do_two(); do_three()</code></pre>

  • 雖然有時(shí)可以在 if/for/while 的同一行跟一小段代碼,但絕不要對(duì)多條子句
    (multi-clause statements) 也這樣做懊渡。也避免折疊這樣的長(zhǎng)行刽射。

    <pre><code>最好不要 (Rather not):
    if foo == 'blah': do_blah_thing()
    for x in lst: total += x
    while t < 10: t = delay()

    明確不要 (Definitely not):
    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()</code></pre>

注釋

--(Comments)

--同代碼不一致的注釋比沒(méi)注釋更差,當(dāng)代碼修改時(shí),始終優(yōu)先更新注釋;
--注釋?xiě)?yīng)該是完整的句子剃执,如果注釋是一個(gè)短語(yǔ)或句子誓禁,首字母應(yīng)該大寫(xiě),除非它是一 個(gè)以小寫(xiě)字母開(kāi)頭的標(biāo)識(shí)符 (永遠(yuǎn)不要修改標(biāo)識(shí)符的大小寫(xiě));
--如果注釋很短肾档,可以省略末尾的句號(hào)摹恰,注釋塊通常由一個(gè)或多個(gè)段落組成辫继,段落是由完整的句子構(gòu)成的,每個(gè)句子應(yīng)該以句號(hào)結(jié)尾俗慈;
--你應(yīng)該在結(jié)束語(yǔ)句的句點(diǎn) (a sentence-ending period) 后使用兩個(gè)空格姑宽;
--用英語(yǔ)書(shū)寫(xiě)時(shí),斷詞和空格是可用的 (When writing English, Strunk and White apply);闺阱;
--非英語(yǔ)國(guó)家的 Python 程序員:請(qǐng)用英語(yǔ)書(shū)寫(xiě)你的注釋炮车,除非你 120% 的確信代碼永遠(yuǎn)不會(huì)被不懂你的語(yǔ)言的人閱讀;
  • 塊注釋(Block Comments)

<pre>--注釋塊通常應(yīng)用于跟隨其后的一些 (或者全部) 代碼酣溃,并和這些代碼有著相同的縮進(jìn) 層次瘦穆。注釋塊中每行以 '#' 和一個(gè)空格開(kāi)始
(除非它是注釋內(nèi)的縮進(jìn)文本),注釋塊內(nèi)的段落以僅含單個(gè) '#' 的行分割;</pre>

  • 行內(nèi)注釋(Inline Comments)

<pre><code>節(jié)儉使用行內(nèi)注釋赊豌。
一個(gè)行內(nèi)注釋是和語(yǔ)句在同一行的注釋扛或,行內(nèi)注釋?xiě)?yīng)該至少用兩個(gè)空格和語(yǔ)句分開(kāi),它們應(yīng)該以一個(gè) '#' 和單個(gè)空格開(kāi)始碘饼;
行內(nèi)注釋不是必需的熙兔,事實(shí)上,如果說(shuō)的是顯而易見(jiàn)事艾恼,還會(huì)使人分心黔姜,不要這樣做:

x = x + 1 # Increment x

但是有時(shí),這樣是有益的:

x = x + 1 # Compensate for border</code></pre>

  • 文本字符串(Documentation Strings)

書(shū)寫(xiě)好的文檔字符串 (又名"docstrings") 的約定蒂萎,在 PEP 257中是永存的。

為所有公共模塊淮椰、函數(shù)五慈、類和方法書(shū)寫(xiě)文檔字符串。文檔字符串對(duì)非公開(kāi)的方法不
是必要的主穗,但你應(yīng)該有一條注釋來(lái)描述這個(gè)方法做什么泻拦;這條注釋?xiě)?yīng)該出現(xiàn)在 "def" 行之后。
PEP 257 描述了好的文檔字符串約定忽媒。一定注意争拐,多行文檔字符串結(jié)尾的 """ 應(yīng)該
單獨(dú)成行,并推薦在其前加一空行晦雨,例如:
<pre><code>
"""Return a foobang
Optional plotz says to frobnicate the bizbaz first.
"""
對(duì)單行的文檔字符串架曹,結(jié)尾的 """ 在同一行也可以。</code></pre>

版本注記

--(Version Bookkeeping)

如果你用Subversion, CVS, or RCS管理你的代碼文件, 可以參照下面的做法:

<pre><code>version = "$Revision$"

$Source$

這幾行文字可以加在模塊中文本字符串的后面闹瞧,用空格與其余代碼部分分開(kāi)</code></pre>

命名慣例

--(Naming Conventions)

  • 首要原則(Overriding Principle)
    對(duì)公眾可見(jiàn)的绑雄,如API中的命名,應(yīng)當(dāng)優(yōu)先考慮名字反映其用途奥邮,而非應(yīng)用万牺;

  • 命名風(fēng)格描述
    <pre><code>有許多不同的命名風(fēng)格罗珍。以下的有助于辨認(rèn)正在使用的命名風(fēng)格,這獨(dú)立于它們的作 用脚粟。
    以下的命名風(fēng)格是眾所周知的:

    • 單個(gè)小寫(xiě)字母 (b)
    • 單個(gè)大寫(xiě)字母 (B)
    • 小寫(xiě)串 (lowercase)
    • 帶下劃線的小寫(xiě)串 (lower_case_with_underscores)
    • 大寫(xiě)串 (UPPERCASE)
    • 帶下劃線的大寫(xiě)串 (UPPER_CASE_WITH_UNDERSCORES)
    • 首字母大寫(xiě)單詞串 (CapitalizedWords) (或 CapWords覆旱、CamelCase -- 因其字母看起來(lái)錯(cuò)落有致,故得此名)核无。有時(shí)這也被稱作StudlyCaps扣唱。
      注意: 在 CapWords 中使用縮寫(xiě),需要把縮寫(xiě)的所有字母大寫(xiě)厕宗。故 HTTPServerError 比 HttpServerError 更好画舌。
    • 混合大小寫(xiě)串 (mixedCase) (與首字母大寫(xiě)串不同之處在于第一個(gè)字符是小寫(xiě)的!)
    • 帶下劃線的首字母大寫(xiě)串 (Capitalized_Words_With_Underscores) (丑陋已慢!)

    還有一種風(fēng)格曲聂,使用特別的短前綴來(lái)將相關(guān)的名字分成組。這在 Python 中不常用佑惠, 但是出于完整性要提一下朋腋。例如,os.stat() 函數(shù)返回
    一個(gè) tuple膜楷,其元素傳統(tǒng)上有 象 st_mode, st_size, st_mtime 等等這樣的名字旭咽。(這樣做是為了強(qiáng)調(diào)與 POSIX 系 統(tǒng)調(diào)用結(jié)構(gòu)體的相關(guān)
    性,這有助于程序員熟悉那些相關(guān)性赌厅。)X11 庫(kù)的所有公開(kāi)函數(shù)以 X 開(kāi)頭穷绵。在 Python 中,這個(gè)風(fēng)格通常認(rèn)為是不必要的特愿,因 為屬性和方法
    名以對(duì)象作前綴仲墨,而函數(shù)名以模塊名作前綴。
    另外揍障,以下用前導(dǎo)或后置下劃線的特殊形式是被公認(rèn)的 (通常這些可以和任何習(xí)慣相 組合):

    • single_leading_underscore:
      (單前導(dǎo)下劃線): 弱的 "內(nèi)部使用 (internal use)" 標(biāo)志目养。 例如,"from M import " 不會(huì)導(dǎo)入以下劃線開(kāi)頭的對(duì)象毒嫡。
    • single_trailing_underscore:
      (單后置下劃線): 習(xí)慣上用于避免與 Python 關(guān)鍵詞的沖突癌蚁。 例如: Tkinter.Toplevel(master, class='ClassName')
    • double_leading_underscore:
      (雙前導(dǎo)下劃線): 當(dāng)用于命名 class 屬性時(shí),會(huì)觸發(fā)名字重整 (name mangling)兜畸。 (在類 FooBar 中努释,boo 變成 FooBarboo;參加下面)咬摇。
    • double_leading_and_trailing_underscore:
      (雙前導(dǎo)和后置下劃線):存在于用戶控制的 (user-controlled) 名字空間的 "magic" 對(duì)象或?qū)傩郧⒔唷@? init, import or file 決不
      要發(fā)明這樣的名字,僅像文檔中那樣使用即可菲嘴。</code></pre>
  • 命名風(fēng)格說(shuō)明
    <pre><code>--避免采用的名字 (Names to Avoid)<pre><code>1 決不要用字符 'l' (小寫(xiě)字母 el)饿自,'O' (大寫(xiě)字母 oh)汰翠,或 'I' (大寫(xiě)字母 eye) 作為單個(gè)字符的變量名。
    2 在一些字體中昭雌,這些字符不能與數(shù)字 1 和 0 區(qū)別開(kāi)复唤。當(dāng)想要使用 'l' 時(shí),用'L' 代替它烛卧。</code></pre>
    --包和模塊名 (Package and Module Names)<pre><code>1 模塊名應(yīng)該是簡(jiǎn)短的佛纫、全部小寫(xiě)的名字∽芊牛可以在模塊名中使用下劃線以提高可讀性 呈宇。
    2 Python 包名也應(yīng)該是簡(jiǎn)短的、全部小寫(xiě)的名字局雄,盡管不推薦使用下劃線甥啄。
    3 因?yàn)槟K名被映射到文件名,有些文件系統(tǒng)大小寫(xiě)不敏感并且截短長(zhǎng)名字炬搭,所以把 模塊名選擇為相當(dāng)短就很重要了
    這在 Unix 上不是問(wèn)題蜈漓,但當(dāng)把代碼遷移到 Mac、Windows 或 DOS 上時(shí)宫盔,就可能是個(gè)問(wèn)題了融虽。當(dāng)一個(gè)用 C 或 C++ 寫(xiě)的擴(kuò)展模塊,
    有一個(gè)伴隨的 Python 模塊來(lái)提供一個(gè)更高層 (例如灼芭,更面向?qū)ο? 的接口時(shí)有额,C/C++ 模塊名有一個(gè)前導(dǎo)下劃線 (如:socket)。</code></pre>
    --類名 (Class Names)<pre><code>幾乎沒(méi)有例外彼绷,類名使用首字母大寫(xiě)單詞串 (CapWords) 的約定谆吴。 內(nèi)部使用的類使用一個(gè)額外的前導(dǎo)下劃線。</code></pre>
    --異常名 (Exception Names)<pre><code>因?yàn)楫惓?yīng)該是類苛预,故類命名約定也適用于異常。然而笋熬,你應(yīng)該對(duì)異常名添加后綴 "Error" (如果該異常的確是一個(gè)錯(cuò)誤)热某。</code></pre>
    --全局變量名 (Global Variable Names)<pre><code>(讓我們希望這些變量只打算用于一個(gè)模塊內(nèi)部。) 這些約定與那些用于函數(shù)的約定差不多胳螟。
    對(duì)設(shè)計(jì)為通過(guò) "from M import " 來(lái)使用的模塊昔馋,應(yīng)采用 all 機(jī)制來(lái)防止導(dǎo) 出全局變量;或者使用舊的約定糖耸,為該類全局變量加一個(gè)前導(dǎo)下劃線
    (可能你想表 明這些全局變量是 "module non-public")秘遏。</code></pre>
    --函數(shù)名 (Function Names)<pre><code>函數(shù)名應(yīng)該為小寫(xiě),必要時(shí)可用下劃線分隔單詞以增加可讀性嘉竟。
    混合大小寫(xiě) (mixedCase) 僅被允許用于這種風(fēng)格已經(jīng)占優(yōu)勢(shì)的上下文 (如: threading.py)邦危,以便保持向后兼容洋侨。</code></pre>
    --函數(shù)和方法的參數(shù) (Function and method arguments)<pre><code>1 對(duì)實(shí)例的方法,總是用 'self' 做第一個(gè)參數(shù)倦蚪。
    2 對(duì)類的方法希坚,總是用 'cls' 做第一個(gè)參數(shù)。
    如果函數(shù)的參數(shù)名與保留關(guān)鍵字沖突陵且,在參數(shù)名后加一個(gè)下劃線裁僧,比用縮寫(xiě)、錯(cuò)誤 的拼寫(xiě)要好慕购。因此 "print" 比 "prnt" 好聊疲。
    (也許使用同義詞來(lái)避免沖突更好。)</code></pre>
    --方法名和實(shí)例變量 (Method Names and Instance Variables)<pre><code>1 采用函數(shù)命名規(guī)則:小寫(xiě)單詞沪悲,必要時(shí)可用下劃線分隔單詞以增加可讀性获洲。
    2 僅對(duì) non-public 方法和實(shí)例變量采用一個(gè)前導(dǎo)下劃線。
    3 為避免與子類命名沖突可训,采用兩個(gè)前導(dǎo)下劃線來(lái)觸發(fā) Python 的命名重整規(guī)則昌妹。
    4 Python 用類名重整這些名字:如果類 Foo 有一個(gè)屬性名為 a, 它不能以 Foo.a 訪問(wèn)握截。(執(zhí)著的用戶還是可以通過(guò) Foo.Fooa 得到訪問(wèn)權(quán)飞崖。)
    通常,雙 前導(dǎo)下劃線僅被用來(lái)避免與基類的屬性發(fā)生名字沖突谨胞。
    注:關(guān)于 names 的作用存在一些爭(zhēng)論 (見(jiàn)下面)固歪。</code></pre>
    --常量(Constants)<pre><code>常量通常是在模塊級(jí)下定義并寫(xiě)入,常使用大寫(xiě)字母和下劃線胯努,其中下劃線分隔單詞牢裳。
    例子包括MAX_OVERFLOW和TOTAL。</code></pre>
    --繼承的設(shè)計(jì) (Designing for inheritance)<pre><code>1 總是確定類的方法和實(shí)例變量 (統(tǒng)稱為屬性) 是否應(yīng)該被公開(kāi)或者不公開(kāi)叶沛。
    如果有 疑問(wèn)蒲讯,選擇不公開(kāi);今后把其改為公開(kāi)比把一個(gè)公開(kāi)屬性改為非公開(kāi)要容易灰署。
    2 公開(kāi)屬性是那些你期望你的類的不相關(guān)的客戶使用判帮,并根據(jù)你的承諾來(lái)避免向后不 兼容變更。非公開(kāi)屬性是那些確定不給第三方使用的溉箕;
    你不保證非公開(kāi)屬性不變,甚至被移除晦墙。這里我們不使用術(shù)語(yǔ) "private",因?yàn)樵?Python 中沒(méi)有屬性是真正私有的
    (沒(méi)有 通常的無(wú)用功 (unnecessary amount of work))肴茄。
    3 另一類屬性是 "subclass API" 的一部分 (在其他語(yǔ)言中通常稱為 "protected")晌畅。 一些類被設(shè)計(jì)為基類,要么被擴(kuò)展寡痰,要么類的某些行為被修改抗楔。
    當(dāng)設(shè)計(jì)這樣的類時(shí),注意明確決定哪些屬性是公開(kāi)的棋凳,哪些是子類 API 的一部分,及哪些是真正僅被 你的基類使用谓谦。
    謹(jǐn)記這些 Python 特色的指導(dǎo)方針:
    公開(kāi)屬性應(yīng)該沒(méi)有前導(dǎo)下劃線贫橙。
    如果公開(kāi)屬性名和保留關(guān)鍵字沖突,在你的屬性名后添加一個(gè)后置下劃線反粥。這比
    縮寫(xiě)或者錯(cuò)誤的拼寫(xiě)更可取卢肃。(然而,盡管這條規(guī)則才顿,對(duì)任何已知是類的變量或者 參數(shù)莫湘,尤其是類方法的第一個(gè)參數(shù),'cls' 是首選拼寫(xiě)方式郑气。)
    注1:參見(jiàn)上面對(duì)類方法的參數(shù)名的建議幅垮。
    對(duì)簡(jiǎn)單的公開(kāi)數(shù)據(jù)屬性 (data attribute),最好只暴露屬性名尾组,沒(méi)有復(fù)雜的訪問(wèn)
    /修改方法 (accessor/mutator methods)忙芒。謹(jǐn)記 Python 為將來(lái)增強(qiáng)提供了一條 容易的途徑,
    你應(yīng)該發(fā)現(xiàn)簡(jiǎn)單數(shù)據(jù)屬性需要增加功能行為讳侨。在那種情況呵萨,
    用特性 (properties) 把功能實(shí)現(xiàn)隱藏在簡(jiǎn)單數(shù)據(jù)屬性訪問(wèn)語(yǔ)法后面。
    注1:特性僅工作于 new-style 的類跨跨。
    注2:嘗試不管功能行為的副作用潮峦,盡管像 cache 之類副作用通常是好的。
    注3:避免對(duì)費(fèi)時(shí)的計(jì)算操作使用特性勇婴;屬性符號(hào)使調(diào)用者相信訪問(wèn)是 (相對(duì))
    廉價(jià)的忱嘹。
    如果確定你的類會(huì)被子類化,并且你有不希望子類使用的屬性耕渴,考慮用兩個(gè)前導(dǎo)
    下劃線拘悦、但沒(méi)有后置下劃線命名它們。這將觸發(fā) Python 的名字重整算法橱脸,把類 名整合進(jìn)屬性名中础米。當(dāng)子類無(wú)意中包含了相同名字的屬性時(shí),
    這有助于避免屬性 名沖突慰技。
    注1:注意僅使用簡(jiǎn)單類名來(lái)重整名字,因此组砚,如果子類使用相同的類名和屬性名
    吻商,你仍然會(huì)名字沖突。
    注2:名字重整使一些應(yīng)用稍有不便糟红,例如調(diào)試和 getattr()艾帐。然而名字重整
    算法有良好的文檔乌叶,也容易手工執(zhí)行。
    注3:不是每個(gè)人都喜歡名字重整柒爸。嘗試在避免意外的名字沖突需求和高級(jí)調(diào)用者
    的可能應(yīng)用之間平衡准浴。</code></pre>
    </code></pre>

編程建議

--(Programming Recommendations)

代碼應(yīng)該按照一種方式編寫(xiě),但是不應(yīng)該不利于在其他python中的應(yīng)用 (PyPy, Jython, IronPython, Cython, Psyco, and such).

例如捎稚,對(duì) a+=b or a=a+b 形式的語(yǔ)句乐横,不要依賴 CPython 對(duì)就地 (in-place) 字 符串連接的高效實(shí)現(xiàn)。那些語(yǔ)句在 Jython 中運(yùn)行很慢今野。對(duì)庫(kù)的性能敏感部分葡公,應(yīng) 該改用 ''.join() 語(yǔ)句。這將保證對(duì)不同的實(shí)現(xiàn)条霜,字符串連接表現(xiàn)為線性時(shí)間催什。

與 None 之類的單件比較,應(yīng)該總是用 'is' or 'is not'宰睡,絕不要用等號(hào)操作符蒲凶。

同樣,當(dāng)你本意是 "if x is not None" 時(shí)拆内,對(duì)寫(xiě)成 "if x" 要小心 -- 例如旋圆,當(dāng) 測(cè)試一個(gè)默認(rèn)為 None 的變量或參數(shù)是否被設(shè)置為其他值時(shí),這個(gè)其他值可能是一種 在布爾上下文中為假的類型 (例如容器)!

使用is not而不是not ... is矛纹,雖然兩者表述的功能相同臂聋,但是前者的可讀性和鐘愛(ài)度更高

<pre><code>Yes:

if foo is not None:
No:

if not foo is None:</code></pre>

當(dāng)使用一些比較的操作命令時(shí),最好能夠用以下6中操作( eq , ne , lt , le , gt , ge ) 而不是依賴其他的一些比較方法或南。

為了減小關(guān)聯(lián)性孩等,functools.total_ordering()提供生成了一些缺失的比較方法。

PEP 207假定Python具有自反性采够,因此解釋器可能交換 y > x 成 x < y , y >= x 成 x <= y , 又或者把 x == y 轉(zhuǎn)換成 x != y肄方。sort() 與min()操作是基于 < 運(yùn)算符,max()函數(shù)使用 > 運(yùn)算符蹬癌。然而, 最好是使用上述的六種方式权她,這樣不會(huì)增加在其他文本中的混淆。

使用def-statement比綁定一個(gè)lambda表達(dá)式的assignment-statement要好

<pre><code>Yes:

def f(x): return 2*x
No:

f = lambda x: 2*x</code></pre>

other example

<pre><code>Yes:

try:
value = collection[key]
except KeyError:
return key_not_found(key)
else:
return handle_value(value)
No:

try:
# Too broad!
return handle_value(collection[key])
except KeyError:
# Will also catch KeyError raised by handle_value()
return key_not_found(key)</code></pre>

<pre><code>Yes:

with conn.begin_transaction():
do_stuff_in_transaction(conn)
No:

with conn:
do_stuff_in_transaction(conn)</code></pre>

<pre><code>Yes:

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)
No:

def foo(x):
if x >= 0:
return math.sqrt(x)

def bar(x):
if x < 0:
return
return math.sqrt(x)</code></pre>

<pre><code>Yes: if foo.startswith('bar'):
No: if foo[:3] == 'bar':
Object type comparisons should always use isinstance() instead of comparing types directly.</code></pre>

<pre><code>Yes: if isinstance(obj, int):

No: if type(obj) is type(1):</code></pre>

<pre><code>Yes: if not seq:
if seq:

No: if len(seq)
if not len(seq)</code></pre>

<pre><code>Yes: if greeting:
No: if greeting == True:
Worse: if greeting is True:</code></pre>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末逝薪,一起剝皮案震驚了整個(gè)濱河市隅要,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌董济,老刑警劉巖步清,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡廓啊,警方通過(guò)查閱死者的電腦和手機(jī)欢搜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)谴轮,“玉大人炒瘟,你說(shuō)我怎么就攤上這事〉诓剑” “怎么了疮装?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)雌续。 經(jīng)常有香客問(wèn)我斩个,道長(zhǎng),這世上最難降的妖魔是什么驯杜? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任受啥,我火速辦了婚禮,結(jié)果婚禮上鸽心,老公的妹妹穿的比我還像新娘滚局。我一直安慰自己,他們只是感情好顽频,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布藤肢。 她就那樣靜靜地躺著,像睡著了一般糯景。 火紅的嫁衣襯著肌膚如雪嘁圈。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,185評(píng)論 1 284
  • 那天蟀淮,我揣著相機(jī)與錄音最住,去河邊找鬼。 笑死怠惶,一個(gè)胖子當(dāng)著我的面吹牛涨缚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播策治,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼脓魏,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了通惫?” 一聲冷哼從身側(cè)響起茂翔,我...
    開(kāi)封第一講書(shū)人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎履腋,沒(méi)想到半個(gè)月后珊燎,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年俐末,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奄侠。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡卓箫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出垄潮,到底是詐尸還是另有隱情烹卒,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布弯洗,位于F島的核電站旅急,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏牡整。R本人自食惡果不足惜藐吮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望逃贝。 院中可真熱鬧谣辞,春花似錦、人聲如沸沐扳。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)沪摄。三九已至躯嫉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間杨拐,已是汗流浹背祈餐。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留戏阅,地道東北人昼弟。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像奕筐,于是被迫代替她去往敵國(guó)和親舱痘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容