[Python] docstringのスタイルと書き方

# はじめに
非プログラミングエンジニアがPythonでdocstringを適切に運用するために情報をまとめた。
本内容では日本語記載を行うが、通常は推奨されない。

## 自身の関連記事
・docstringのスタイルと書き方。（2021/01/30）←本記事
　[[Python] docstringのスタイルと書き方](https://qiita.com/flcn-x/items/393c6f1f1e1e5abec906)
・VSCodeでのdocstring生成に関する機能拡張。（2021/02/01）
　[[Python] VSCodeでのdocstring生成拡張](https://qiita.com/flcn-x/items/724fb59bcdf54758aead)
・docstringを利用した関数テスト。（2021/02/07）
　[[Python] 関数のテストとその手法概要（dcstest, unittest, pytest）](https://qiita.com/flcn-x/items/fcbbc2fb291b970290f2)

# docstringとは
コード内で文字を記載する際の方法の一つ。
(#)をいれることでそれ以降がコメントとなる。コメントはコード内で無視される。
(""")で囲うことでdocstringとなる。

>コメントは文字列リテラル内に入っていないハッシュ文字 (#) から始まり、同じ物理行の末端で終わります。
>非明示的な行継続規則が適用されていない限り、コメントは論理行を終端させます。
>コメントは構文上無視されます; コメントはトークンになりません。
[2.1.3. コメント (Comments)](https://docs.python.org/ja/3.6/reference/lexical_analysis.html#comments)

```Python
# これはコメント

""" これはdocstring
"""
```

なお、docstring (""")で囲まれた領域は複数行にまたがることが可能なため、上記の比明示的な行継続規則であり、(#)を入れてもコメントにはならない。

```Python
""" これはdocstring
# これはコメントにはならない
"""
```

docstringはコメントとは異なり、いくつかの役割がある。

 * モジュールやクラス、関数の説明文( \_\_doc\_\_ 属性)
 * 対話的なテスト(doctest)の実行  ( [26.3.1. 簡単な利用法: docstring 中の実行例をチェックする](https://docs.python.org/ja/3.6/library/doctest.html?highlight=docstring) )

## コーディング時の利用
docstringを記載した場合、関連付けられた関数などはその内容の属性を得ているため、エディタやhelp関数などでその記述内容を表示できる。
これは、ソースコードを直接見る際の利用に限られるコメントとは異なる。

## ドキュメント化への利用(Sphinx)
ドキュメント作成に使用されるSphinxなどはdocstringを構文解析することでドキュメントの自動生成を行うことができる。
SphinxはPython公式ドキュメント作成にも用いられている。

>このツールはもともと、Python のドキュメンテーション用に作られました、
今では幅広い言語のプロジェクトでドキュメント作成を容易にするツールとして利用されています。
[Sphinx HP](https://www.sphinx-doc.org/ja/master/)

# 記載スタイル

主に2つのガイドによって記載方法の基本ルールが定められている。

 * Pythonのコーディングスタイルガイドである [PEP 8](https://pep8-ja.readthedocs.io/ja/latest/)
 * docstringのスタイルガイドである [PEP 257](https://www.python.org/dev/peps/pep-0257/)

また、ガイド以外の記載スタイルにはいくつかのスタイルがある。

 * reStructuredTextスタイル
 * Googleスタイル
 * NumPyスタイル
 
## スタイルガイドの簡易紹介

スタイルガイド内ではdocstringの記載方法に関する記載がある。
様々な開発環境、ライブラリで前提として運用されている場合があるので、出来れば順守したほうが良い。

 * 1行は***72文字まで***とする。
 * import文はコメントの直後に記述する。
 * 概要のみの1行、詳細な説明の複数行を記述する。
 * ***1行目は概要のみ***簡潔に記述する。
 * 複数行の場合は、空行を挟んで説明を記述する。
 * docstringと対象定義の間に空行を挟まない。
 * モジュールの場合は、公開するクラス、関数などについて1行の説明を付けて一覧化する。
 * クラスの場合は、何をするクラスなのかの概要、外部に公開するメソッドやインスタンス変数などを記述する。
 * クラスの場合は、冒頭ではdocstringとの間に空行を挟む。
 * 関数の場合は、何をするのかの概要、パラメータ、戻り値、発生する例外などについて記述する。

### モジュール
```Python
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""概要を簡潔に1行で記載する。

       * 公開するクラス、関数などについて1行の説明を付けて一覧化する。(1行は72文字まで)
       * ソースコードの始め(import文より前)に記載する。

"""
```

### 関数
```Python
def func(): # 関数であれば物理行空白明けずにdocstringを記載する。
    """概要を簡潔に1行で記載する。詳細は改行、空行を挟んで記載する。

　　パラメータ、戻り値、発生する例外など(複数行であれば空行を挟む。

　　などなど
    """
    pass # 関数内の動作
```

# reStructuredTextスタイル

reStructuredTextはSphinxの軽量マークアップ言語として使用されている。

>reStructuredTextは軽量マークアップ言語のひとつ。
ソースコードの状態で高い可読性を持つように設計されている。
パーサはテキスト処理フレームワークであるDocutilsのコンポーネントのひとつであり、Pythonで実装されている。
[@wiki](https://ja.wikipedia.org/wiki/ReStructuredText)

また、Sphinxにて指定されているドキュメント化に関する記載方法となっている。

>SphinxはreStructuredTextをマークアップ言語として使用しています。Sphinxの強さの多くの部分はreStructuredTextと、そのパース、変換プログラム群である、Docutilsからきています。
[Sphinx HP](https://www.sphinx-doc.org/ja/master/)

なお、Sphinxでは拡張によって他の2つスタイルの解析も可能であるようになった。
そのため、スタイル自体の選択はSphinxを利用したドキュメント化に対しては自由といえる。
有効化に関しては、Sphinxの設定ファイルであるconf.py内の ***extensions*** に ***sphinx.ext.napoleon*** を追加する。

```Python
# autodocはSphinxでソースコードから自動解析するもの
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon']
```

>Napoleonは、 NumPy スタイルおよび Google\`_スタイル（\`Khan Academy\`_が推奨しているスタイル）の両方でSphinxがパースできるようにしてくれる :doc:../extensions\` です。
[NumPy および Google スタイルの docstring をドキュメントに取り込む](https://www.sphinx-doc.org/ja/1.5/ext/napoleon.html)

## キーワード
reStructuredTextスタイルで定義されたキーワードを以下にまとめる。
※全キーワードは[Sphinx-Domains: 詳細情報フィールドのリスト](https://www.sphinx-doc.org/ja/master/usage/restructuredtext/domains.html#the-python-domain)を参照すること。

|キーワード|内容|
|---|---|
|param, parameter, arg, argument, key, keyword|引数の説明|
|type|引数の型|
|raises, raise, except, exception|例外処理の説明|
|var, ivar, cvar|変数の説明|
|vartype|変数の型|
|returns, return|戻り値の説明|
|rtype|戻り値の型|

## 記述例

reStructuredTextスタイルでの記述例を以下に示す。

```Python
def func(arg1, arg2):
    """概要
    
    詳細説明
    
    :param int 引数(arg1)の名前: 引数(arg1)の説明
    :param 引数(arg2)の名前: 引数(arg2)の説明
    :type 引数(arg2)の名前: 引数(arg2)の型
    :return: 戻り値の説明
    :rtype: 戻り値の型
    :raises 例外の名前: 例外の定義
    """
    value = arg1 + arg2
    return value
```

# Googleスタイル
Googleが提唱したDocstringの記法の一つ。
スタイルの差のため、基本的な内容・運用方法は同様である。
ただ、Sphinx公式ドキュメントでも以下のように記載あるように、見た目の好みが一つの判断要素のようである。

>ReStructuredText は偉大ですが、視覚的に高密度になり、 docstrings が読み難くなります。
[Sphinx: NumPy および Google スタイルの docstring をドキュメントに取り込む](https://www.sphinx-doc.org/ja/1.5/ext/napoleon.html)

キーワードを以下にまとめる。
なお、ToDoについては、前述とは別にSphinxのconf.pyを変更する必要がある。

```Python
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon', 'sphinx.ext.todo']
todo_include_todos = True
```
## セクション
Googleスタイルで定義されたセクションを以下にまとめる。
※全セクションは[Google Python Style Guide](https://google.github.io/styleguide/pyguide.html#s3.8.1-comments-in-doc-strings)の ***3.8 Comments and Docstrings*** を参照すること。

|セクション|内容|
|---|---|
|Attributes|クラスの属性の説明|
|Args|引数の説明|
|Returns|retrun文での戻り値の説明|
|Yieds|yeild文での戻り値の説明|
|Raises|例外処理の説明|
|Examples|クラスや関数の実行例|
|Note|なんでも|
|Todo|Todoリストを記載|

## 記述例
Googleスタイルでの記述例を以下に示す。

```Python
def func(arg1, arg2):
    """概要

    詳細説明

    Args:
        引数(arg1)の名前 (引数(arg1)の型): 引数(arg1)の説明
        引数(arg2)の名前 (:obj:`引数(arg2)の型`, optional): 引数(arg2)の説明

    Returns:
        戻り値の型: 戻り値の説明

    Raises:
        例外の名前: 例外の説明

    Yields:
        戻り値の型: 戻り値についての説明

    Examples:

        関数の使い方

        >>> func(5, 6)
        11

    Note:
        注意事項や注釈など

    """
   value = arg1 + arg2
   return value
```



# NumPyスタイル
Pythonで多く使用されるNumPyにおける[ガイドライン]()に沿ったスタイル。
演算系・解析系のライブラリにおいて、採用されている場合がある。

## セクション

NumPyスタイルで定義されたセクションを以下にまとめる。
※全セクションは[numpydoc docstring guide](https://numpydoc.readthedocs.io/en/latest/format.html#sections)の ***Sections*** を参照すること。

|セクション|内容|
|---|---|
|Attributes|クラスの属性の説明|
|Parameters|引数の説明|
|Returns|return文での戻り値の説明|
|Yields|yeild文での戻り値の説明|
|Raises|例外処理の説明||
|Examples|クラスや関数の実行例|
|Notes|なんでも|
|See Also|関連して参照|

## 記述例
Numpyスタイルでの記述例を以下に示す。

```Python
def func(arg1, arg2):
    """概要

    詳細説明

    Parameters
    ----------
    引数(arg1)の名前: 引数(arg1)の型
        引数(arg1)の説明
    引数(arg2)の名前: 引数(arg2)の型
        引数(arg2)の説明

    Returns
    -------
    戻り値の名前: 戻り値の型
        戻り値の説明

    Raises
    ------
    例外の名前
        例外の説明

    Examples
    --------
    >>> func(5, 6)
    11

    Notes
    -----
    なんでも

    """
    value = arg1 + arg2
    return value
```

# 最後に
docstringのルールを確認した。
実際の利用に関しては、丁寧に記載して時間がかかるのを避けたいのが心情だが、複数のスタイルや独自ルールが同時に存在する状況は好ましくない。
プロジェクトの運用状況、メンバでの認識、Sphinxを用いたドキュメント化、テスト方法含めてベストは選択ができるようになりたい。

# 参考・引用

[ 自身の記事 ]
[[Python] VSCodeでのdocstring生成拡張](https://qiita.com/flcn-x/items/724fb59bcdf54758aead)

[ 基本 ]
[公式：PEP 8](https://pep8-ja.readthedocs.io/ja/latest/)
[公式：PEP 257](https://www.python.org/dev/peps/pep-0257/)
[参考：［Python入門］docstringの書き方](https://www.atmarkit.co.jp/ait/articles/1912/06/news025.html#docstringstyles)
[ ReStructuredTextスタイル ]
[公式：Sphinx Python-Domain (ja)](https://www.sphinx-doc.org/ja/master/usage/restructuredtext/domains.html#the-python-domain)
[ Googleスタイル ]
[公式：Google Python Style Guide](https://google.github.io/styleguide/pyguide.html#s3.8.1-comments-in-doc-strings)
[参考：GoogleスタイルのPython Docstringの入門](https://qiita.com/11ohina017/items/118b3b42b612e527dc1d)
[ NumPyスタイル ]
[公式：numpydoc docstring guide](https://numpydoc.readthedocs.io/en/latest/format.html)
[参考：[Python]可読性を上げるための、docstringの書き方を学ぶ（NumPyスタイル）](https://qiita.com/simonritchie/items/84c4d4b2528309c30359)