Python部落(www.freelycode.com)組織翻譯, 禁止轉載
概要
本篇PEP文檔主要對Python函數文檔字符串的語義和規範進行了相關闡述。
基本原理
PEP的目標是讓程序猿寫出的Python函數文檔字符串(Doctring)高度結構化、規範化:文檔字符串應該包含什麼,如何書寫(在文檔字符裡避免使用標記語法的情況下)。 PEP中包含的是約定俗成的東西,不是定律或嚴苛的語法。
一個通用的公約給編程提供了可維護性,清晰性,一致性,同時也提供了良好的編程習慣的基礎。但它從來不會強迫你去按照它的標準做你不喜歡的事情。這就是Python!」
—Tim Peters on comp.lang.python, 2001-06-16
如果你不按約定編寫代碼,最壞的情況是,寫出來的代碼很邋遢。但有些軟體代碼的編寫必須按照約定來(比如 Docutils [3] docstring 的處理系統[1] [2] )。總而言之,遵守約定,能給你帶來最好的結果。.
詳述
什麼是 Docstring?
Docstring是模塊、類、方法中的第一個聲明性描述說明。比如docstring變成 __doc__ 類的special attribute of that object.
所有的modules一般都有Docstring,模塊中的類和方法也應該有Doctring。公共方法 (包含 __init__ 構造器的方法) 也應該有Doctring。一個包的描述信息一般在包目錄中文件__init__.py的Doctring中。
字符串類說明信息在Python代碼中隨處可見,通常用稱為文檔說明的一部分。這些信息不會被Python字節碼編譯器識別到,也不能被運行時對象屬性訪問。但是,有兩類附加的docstring能被軟體工具提取出來。
1. 在一個模塊、類或者__init__ 方法中一開始就出現的字符串描述信息,我們稱之為 "attribute docstrings"。
2. 緊跟在一個 docstring 後面的字符串描述信息,被稱為 "additional docstrings"。
請參考 PEP 258 , "Docutils Design Specification" [2] ,裡面有關於"attribute docstrings"和"additional docstrings"的詳細說明。
下面是三種情況下,Docstring的一般寫法:
正常情況下: """三個雙引號""" (單純用三個雙引號引起來)
如果有反斜線: r"""raw triple double quotes""" (在開頭加字幕r)
如果使用統一字符編碼標準:u"""Unicode triple-quoted strings""" . (在開頭加字幕u)
一共有兩種Docstring,單行的和多行的:
單行 Docstrings
單行的字符串文檔是最常見的,比如:
def kos_root():
"""Return the pathname of the KOS root directory."""
global _kos_root
if _kos_root: return _kos_root
...
注意:
就算只有一行,也要用三個雙引號,方便後期擴展。
Docstring 正文前後的雙引號都要在一行,這樣更美觀一些。
Docstring 前後都不要留空行。
Docstring 描述的是一個階段性的結果。 它預期性的告訴我們某個方法的具體功能信息("執行某個任務"或"返回某類值"),不是描述;比如,不要這麼寫「返回 路徑」。 ???
單行 docstring 的內容不能是對方法和參數簡單的重複描述,不要像下面那樣寫:
def function(a, b):
"""function(a, b) -> list"""
內省機制:Python的內省機制還是比較強大的。所謂內省,實際上主要是指在runtime獲得一個對象的全部類型信息。這樣可以提供更好的編程靈活性。
這種類型的文檔字符串只適合C函數(比如內嵌函數),因為C中沒有自省的機制。然而,返回值的類型不能通過內省確定,因此應在Docstring中加以說明。因此,文檔字符串的首選形式是這樣的:
def function(a, b):
"""Do X and return a list."""
(Of course "Do X" should be replaced by a useful description!)
多行 Docstrings
多行 docstrings 首先包含一個概述行,緊跟著空一行,然後跟著更加詳細的描述信息。概述行會被自動索引工具識別並處理,所以概述行必須是獨自佔用一行且和後續描述間空一行。概述行可以和開始的雙引號在一行,也可以另起一行,獨佔第二行。整個Docstring的縮進都應該和第一行保持一致 (可以參考下面的例子)。
通常,在給一個類做文檔注釋時,在所有Docstring(單行和多行)的末尾插入一個空行,類的每個方法之間由一個空行分隔開,所以,需要在Docstring跟第一個方法之間留一個行空行。
一個獨立可運行的腳本中的Docstring應當包含該腳本的使用說明信息。 調用腳本的過程中,如果參數用錯或缺失,應能夠列印錯誤信息 (或者用於 "-h" 選項,用來顯示幫助信息).。這樣的 docstring 應該描述出腳本的功能、命令行語法、環境變量和文件信息。 使用說明應儘可能詳細和充分,能夠指導新用戶正確的使用腳本,同時對於高級用戶而言,也應在該Docstring裡獲取到這個腳本的所有選項和參數說明。
一個模塊的docstring應該列出該模塊能夠輸出的類、異常、方法 (以及其他的一些對象)的對應簡述信息,每個對象的描述獨佔一行。 一個包的docstring(比如docstring of the package's __init__.py module) 應該列出包的模塊清單和子包清單。
一個方法的docstring應該簡述它的功能、參數、返回值和類型、異常、約束等。還有可選參數。還應說明這些關鍵字參數是否屬於接口的一部分。
一個類的docstring應該包含這個類的功能概述、公共方法清單、實例變量清單。如果這個類設計的可以作為父類,而且給子類預留了相應的接口,那麼,這個接口應該在docstring中單獨列出。除此以外,這個類的構造方法的文檔信息應該在 __init__ 方法的docstring中表述。具體到方法的話,各自應該有自己的docstring。
如果一個類是另一個類的子類,而且這個類的幾乎完全繼承了父類,那麼要在它的docstirng中應該提到這些信息,以及與父類的不同之處。使用動詞 "override" 指明某個子類的方法是重寫了父類的。使用動詞 "extend" 指明,子類的某個方法完全繼承了父類的方法,並做了功能的擴展。
當連續的代碼中的方法的參數包含大寫的情況時,不要使用Emacs 編輯器的格式化功能。Python是大小寫敏感的,參數名稱即可被用作關鍵字參數,因此 docstring 中應該把參數名描述準確。最好是每行列一個參數。比如:
def complex(real=0.0, imag=0.0):
"""Form a complex number.
Keyword arguments:
real -- the real part (default 0.0)
imag -- the imaginary part (default 0.0)
"""
if imag == 0.0 and real == 0.0:
return complex_zero
...
除非所有的Docstring內容正好佔用一行的情況,才把閉合側的雙引號和開始的引號寫在一行。如此一來,Emacs編輯器中的fill-paragraph命令就能用在這個地方了。
Docstring 縮進的處理
文檔字符串處理工具會把Docstring的第二行開始到最後一行的縮進部分進行等長刪除,刪除部分的長度為這幾行中最短的縮進值。Docstring第一行中縮進都是沒有意義的,換行符也是,會被自動處理刪除掉。後續代碼行中的相對縮進則全部保留。Docstring前後的空白行不應保留。
代碼比語言更精準,下面是這個算法的實現:
def trim(docstring):
if not docstring:
return ''
# Convert tabs to spaces (following the normal Python rules)
# and split into a list of lines:
lines = docstring.expandtabs().splitlines()
# Determine minimum indentation (first line doesn't count):
indent = sys.maxint
for line in lines[1:]:
stripped = line.lstrip()
if stripped:
indent = min(indent, len(line) - len(stripped))
# Remove indentation (first line is special):
trimmed = [lines[0].strip()]
if indent < sys.maxint:
for line in lines[1:]:
trimmed.append(line[indent:].rstrip())
# Strip off trailing and leading blank lines:
while trimmed and not trimmed[-1]:
trimmed.pop()
while trimmed and not trimmed[0]:
trimmed.pop(0)
# Return a single string:
return '\n'.join(trimmed)
樣例中的docstring包含兩個換行符,因此長度為3行。第1行和第3行為空行:
def foo():
"""
This is the second line of the docstring.
"""
舉例說明:
>>> print repr(foo.__doc__)
'\n This is the second line of the docstring.\n '
>>> foo.__doc__.splitlines()
['', ' This is the second line of the docstring.', ' ']
>>> trim(foo.__doc__)
'This is the second line of the docstring.'
經過裁剪處理後,下面兩段代碼的Docstring是等價的:
def foo():
"""A multi-line
docstring.
"""
def bar():
"""
A multi-line
docstring.
"""
英文原文: https://www.python.org/dev/peps/pep-0257/
譯者: cg2580