Pythonのdocstring(ドキュメンテーション文字列)の書き方

Modified: | Tags: Python

Pythonでは、関数やクラスなどの定義の先頭に記述された文字列が、docstring(ドックストリング、ドキュメンテーション文字列)として扱われる。

IDEやエディタによってはキーボードショートカットでdocstringを表示させて内容を確認できる。またPyCharmなどでは、docstringの情報をもとに静的解析して警告を出してくれる。

docstringの表示・出力方法

以下のように関数にdocstringを記述する。docstring自体の書き方は後述。

def my_func():
    """docstring-test
    line1
    line2
    line3
    """
source: docstring.py

__doc__属性

docstringは__doc__属性に文字列として格納されている。print()で出力できる。

print(my_func.__doc__)
# docstring-test
#     line1
#     line2
#     line3
#     

print(type(my_func.__doc__))
# <class 'str'>
source: docstring.py

組み込み関数help()

Jupyter Notebookやターミナルでの対話環境(pythonまたはpython3コマンドで起動するPythonインタプリタ)で、組み込み関数help()に対象のオブジェクトを渡して実行すると、そのdocstringが対話的ヘルプシステムで出力される。

help(my_func)
# Help on function my_func in module __main__:
# 
# my_func()
#     docstring-test
#     line1
#     line2
#     line3
# 
source: docstring.py

ターミナルでの対話型ヘルプシステムはqで終了できる。

IDEやエディタでの表示

IDEやエディタによってはdocstringの内容をショートカットキーなどで表示して確認できる。いくつか例を示す。

Jupyter Notebook

Jupyter Notebookでは、対象の関数などにカーソルを合わせてshift + tabでツールチップにdocstringが表示される。さらにshiftを押したままtabを連打すると詳細表示、分割表示と表示方式が変化する。

Visual Studio Code (VSCode)

Python拡張機能をインストールしたVisual Studio Code (VSCode)では、マウスポインタを対象の関数などに合わせるとツールチップにdocstringが表示される。カーソルを合わせてショートカットcommand + k, command + i(またはcontrol + k, control + i)でも表示できる。

docstringの基本的な書き方

関数やクラスにおけるdocstringの基本的な書き方を示す。引数や返り値などのスタイルは後述。

定義の先頭にトリプルクォート('''または""")で囲んで文字列を記述するのが基本。

def my_func():
    """docstring-test
    line1
    line2
    line3
    """
source: docstring.py

文字列であればいいので、シングルクォート'やダブルクォート"でもdocstringとなる。ただし、一行であっても慣例的にトリプルクォートが使われることが多い。

def my_func2():
    'docstring-test'

print(my_func2.__doc__)
# docstring-test
source: docstring.py

定義の先頭でないとdocstringとならない。文字列の前に式などが記述されているとダメ。

def my_func_error():
    a = 100
    """docstring-test
    line1
    line2
    line3
    """

print(my_func_error.__doc__)
# None
source: docstring.py

クラスでも同様。定義の先頭に文字列を記述する。

class MyClass:
    """docstring-test
    line1
    line2
    line3
    """

print(MyClass.__doc__)
# docstring-test
#     line1
#     line2
#     line3
#     
source: docstring.py

doctestによるテスト

docstringの中に入出力例を書くと、標準ライブラリのdoctestモジュールを使ってテストを実行できる。

簡単なサンプルは以下の通り。

def add(a, b):
    '''
    >>> add(1, 2)
    3
    >>> add(5, 10)
    15
    '''

    return a + b

テストの実行方法などの詳細は以下の記事を参照。

docstringの書き方のスタイル(引数や返り値など)

docstringの中には関数の引数や返り値の説明や型などを記述するが、書き方のフォーマットは特に統一されていない。

以下、代表的な3つのスタイルの例を示す。

  • reStructuredText(reST)スタイル
  • NumPyスタイル
  • Googleスタイル

読む人が理解できるスタイルであれば神経質になる必要はないが、所属組織やプロジェクトのコーディング規約がなければこれらのスタイルを参考にするといいだろう。

代表的なスタイルはドキュメント化やIDE・エディタでの補助機能に対応しているという利点もある。

reStructuredTextスタイルだけでなく、NumPyスタイルとGoogleスタイルのdocstringもSphinxを使ってドキュメントを自動的に生成(html化)することが可能。

IDEやエディタ(およびプラグイン)によっては対応しているスタイルであれば型のヒントの表示やエラーチェックをしてくれるものもある。

例えば、Pythonの統合開発環境であるPyCharmでは3つすべてのスタイルに対応している。

また、Python3.0以降では関数アノテーション(Function Annotations)という仕組みによって、関数の引数や返り値にアノテーション(注釈)を記述できる。後述。

reStructuredText(reST)スタイル

def func_rest(param1, param2):
    """Summary line.

    :param param1: Description of param1
    :type param1: int
    :param param2: Description of param2
    :type param2: str
    :returns: Description of return value
    :rtype: bool
    """
    return True
source: docstring.py

reSTスタイルはサードパーティライブラリRequestsなどで採用されている。以下が実際のコード例。

def resolve_proxies(request, proxies, trust_env=True):
    """This method takes proxy information from a request and configuration
    input to resolve a mapping of target proxies. This will consider settings
    such a NO_PROXY to strip proxy configurations.

    :param request: Request or PreparedRequest
    :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs
    :param trust_env: Boolean declaring whether to trust environment configs

    :rtype: dict
    """
source: utils.py

NumPyスタイル

numpydocというNumPyのドキュメント用のSphinx拡張機能に対応したスタイル。

def func_numpy(param1, param2):
    """Summary line.

    Extended description of function.

    Parameters
    ----------
    param1 : int
        Description of param1
    param2 : str
        Description of param2

    Returns
    -------
    bool
        Description of return value
    """
    return True
source: docstring.py

NumPyのほかpandasでも使われている。

pandasの実際のコード例は以下の通り。

def get_compressed_ids(
    labels, sizes: Shape
) -> tuple[npt.NDArray[np.intp], npt.NDArray[np.int64]]:
    """
    Group_index is offsets into cartesian product of all possible labels. This
    space can be huge, so this function compresses it, by computing offsets
    (comp_ids) into the list of unique labels (obs_group_ids).

    Parameters
    ----------
    labels : list of label arrays
    sizes : tuple[int] of size of the levels

    Returns
    -------
    np.ndarray[np.intp]
        comp_ids
    np.ndarray[np.int64]
        obs_group_ids
    """
source: sorting.py

Googleスタイル

GoogleのPythonスタイルガイドの中で定められているdocstringのスタイル。

def func_google(param1, param2):
    """Summary line.

    Extended description of function.

    Args:
        param1 (int): Description of param1
        param2 (str): Description of param2

    Returns:
        bool: Description of return value

    """
    return True
source: docstring.py

TensorFlowの実際のコード例は以下の通り。

def size_internal(input, name=None, optimize=True, out_type=dtypes.int32):
  # pylint: disable=redefined-builtin,protected-access
  """Returns the size of a tensor.

  Args:
    input: A `Tensor` or `SparseTensor`.
    name: A name for the operation (optional).
    optimize: if true, encode the size as a constant when possible.
    out_type: (Optional) The specified non-quantized numeric output type of the
      operation. Defaults to `tf.int32`.

  Returns:
    A `Tensor` of type `out_type`. Defaults to `tf.int32`.
  """
source: array_ops.py

関数アノテーション

Python3.0以降では関数アノテーション(Function Annotations)という仕組みによって、関数の引数や返り値にアノテーション(注釈)となる式を記述できる。

def func_annotations_type(x: str, y: int) -> str:
    return x * y

関数アノテーションは単なる注釈なので、例えば上の例のように型を記述した場合でも実行時にチェックされたりはしないが、IDEやエディタによってはその情報をもとに処理を行うものもある。

詳細は以下の記事を参照。

関数アノテーションとdocstringは二者択一ではなく、型は関数アノテーション、詳しい説明文はdocstringというように併用して記述する例が多い。

関連カテゴリー

関連記事