[Advanced Python] 16 - Google style guide for programming

Ref: Python 風格指南 - 內容目錄html

這裏主要記錄一下值得注意的地方。python

 

Python語言規範

Lint:vsCode自帶api

導入:完整路徑app

異常socket

  Ref: [Python] 07 - Statements --> Functionside

  首先,自定義異常,基於「異常基類」 class Error(Exception);函數

  其次,except捕獲全部異常過於魯莽;post

  最後,鼓勵使用finally執行「資源清理工做「。學習

全局變量:避免使用,考慮下」類變量「來代替。fetch

嵌套/局部/內部類或函數

  推薦使用!

  對「類中類」狀況的序列化(pickled)帶來問題。

列表推導(List Comprehensions):太複雜的仍是考慮map, reduce, filter。

默認迭代器和操做符:優先使用「省內存的迭代器方法";

生成器:」沒有「缺點

Lambda函數

  適用於單行函數;

  對於常見的操做符,例如乘法操做符,使用 operator 模塊中的函數以代替lambda函數。

條件表達式:適合單行,例如 if cond else 2

默認參數值

  默認參數只在模塊加載時求值一次。若是參數是列表或字典之類的可變類型, 這可能會致使問題。

# 使用 None間接表達
def foo(a, b=None):
         if b is None:
             b = []

# 而不是直接用」可變類型「做爲默認參數
def foo(a, b=[])

屬性(properties):有必要替代setter getter。

True/False的求值

按直覺來說,就是全部的」空」值都被認爲是false。  

」布爾量「 使用 is 或者 is not。

空列表就是None。

注意 is 和 == 的區別,以下:

>>> a is []
False
>>> a == []
True
>>> a
[]

過期的語言特性:有新的就用新的

詞法做用域(Lexical Scoping)

嵌套的Python函數能夠引用外層函數中定義的變量,可是不可以對它們賦值。(鼓勵使用)

i = 4
def foo(x):
    def bar():
        print i,
    # ...
    # A bunch of code here
    # ...
    for i in x:  # Ah, i *is* local to Foo, so this is what Bar sees
        print i,
    bar()

函數與方法裝飾器

最多見的裝飾器是@classmethod@staticmethod,用於將常規函數轉換成類方法或靜態方法。

實例方法(普通方法)—————————隨着實例屬性的改變而改變

類方法(不管是類調用仍是實例調用)——都是類屬性的值,不隨實例屬性的變化而變化

靜態方法———————————————不能夠訪問類屬性,故直接輸出傳入方法的值

線程:不要依賴內建類型的原子性。

威力過大的特性

Python是一種異常靈活的語言, 它爲你提供了不少花哨的特性, 諸如元類(metaclasses), 字節碼訪問, 任意編譯(on-the-fly compilation), 動態繼承, 對象父類重定義(object reparenting), 導入黑客(import hacks), 反射, 系統內修改(modification of system internals), 等等.

優勢:強大的語言特性, 能讓你的代碼更緊湊;

缺點:使用這些很」酷」的特性十分誘人, 但不是絕對必要. 使用奇技淫巧的代碼將更加難以閱讀和調試. 開始可能還好(對原做者而言), 但當你回顧代碼, 它們可能會比那些稍長一點可是很直接的代碼更加難以理解;

結論:在你的代碼中避免這些特性.

 

 

Python風格規範

分號:不要

行長度:80 chars at most;括號就有隱式鏈接屬性。

括號:寧缺毋濫

縮進:四個空格

空行:兩行和一行兩種模式

空格:照舊便可

Shebang:main文件寫 #/usr/bin/python3

若是一個類不繼承自其它類,就顯式的從object繼承. 嵌套類也同樣。

class OuterClass(object):
  class InnerClass(object):
    pass

字符串

免在循環中用+和+=操做符來累加字符串. 因爲字符串是不可變的, 這樣作會建立沒必要要的臨時對象, 而且致使二次方而不是線性的運行時間。

在循環結束後用 .join 鏈接列表,一次性鏈接成一個字符串

items = ['<table>']
for last_name, first_name in employee_list:
  items.append('<tr><td>%s, %s</td></tr>' % (last_name, first_name))
items.append('</table>')
employee_table = ''.join(items)

文件和sockets:使用with...as

導入格式:每一個導入應該獨佔一行;完整包路徑按字典序排序, 忽略大小寫。

語句:一般每一個語句應該獨佔一行

控制訪問:可考慮屬性(property)

命名

命名約定

    1. 所謂」內部(Internal)」表示僅模塊內可用, 或者, 在類內是保護或私有的.
    2. 用單下劃線(_)開頭表示模塊變量或函數是protected的(使用from module import *時不會包含).
    3. 用雙下劃線(__)開頭的實例變量或方法表示類內私有.
    4. 將相關的類和頂級函數放在同一個模塊裏. 不像Java, 不必限制一個類一個模塊.
    5. 對類名使用大寫字母開頭的單詞(如CapWords, 即Pascal風格), 可是模塊名應該用小寫加下劃線的方式(如lower_with_under.py). 儘管已經有不少現存的模塊使用相似於CapWords.py這樣的命名, 但如今已經不鼓勵這樣作, 由於若是模塊名碰巧和類名一致, 這會讓人困擾.
Python之父Guido推薦的規範
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  

Main函數

def main():
      ...

if __name__ == '__main__':
    main()

 

 

註釋之美 

TODO註釋

# TODO(kl@gmail.com): Use a "*" here for string repetition.
# TODO(Zeke) Change this to use relations.

 

文檔字符串

毫不要描述代碼。假設閱讀代碼的人比你更懂Python, 他只是不知道你的代碼要作什麼。

一個文檔字符串應該這樣組織:

    • 首先是一行以句號, 問號或驚歎號結尾的概述(或者該文檔字符串單純只有一行).
    • 接着是一個空行.
    • 接着是文檔字符串剩下的部分, 它應該與文檔字符串的第一行的第一個引號對齊.

Function

一個函數必需要有文檔字符串, 除非它知足如下條件:

    1. 外部不可見
    2. 很是短小
    3. 簡單明瞭
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

 

Class

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

 

End.

相關文章
相關標籤/搜索