コメント(#)/ docstring(""")
『Python』では『#』で一行コメントを書き、三重引用符(『"""』または『'''』)で複数行にわたるdocstringを書きます。docstringは関数・クラス・モジュールに付けるドキュメントコメントで、『help()』関数や各種ドキュメント生成ツールが自動的に読み取ります。
構文
# 一行コメント: # の後にスペースを1つ空けて書くのが慣習です。
# 関数・クラス・モジュールの直後に書く三重引用符がdocstringです。
def 関数名(引数):
"""一行で収まる場合はこの形式で書きます。"""
pass
def 関数名(引数):
"""複数行のdocstringの概要行。
詳細説明をここに書きます。概要行と詳細の間は空行を1行入れます。
"""
pass
# Google スタイル
def 関数名(引数1, 引数2):
"""概要を一行で書きます。
Args:
引数1 (型): 説明。
引数2 (型): 説明。
Returns:
型: 戻り値の説明。
Raises:
例外クラス: 発生条件の説明。
"""
pass
# NumPy スタイル
def 関数名(引数1, 引数2):
"""概要を一行で書きます。
Parameters
----------
引数1 : 型
説明。
引数2 : 型
説明。
Returns
-------
型
戻り値の説明。
"""
pass
コメント・docstring 一覧
| 記法 | 概要 |
|---|---|
| # テキスト | 一行コメントです。『#』以降の行末までがコメントになります。コードの後ろに書くインラインコメントと、コードの上に書くブロックコメントの2種類があります。 |
| """テキスト""" | 三重ダブルクォートによるdocstringです。関数・クラス・モジュールの本体の先頭に書きます。 |
| '''テキスト''' | 三重シングルクォートによるdocstringです。機能は『"""』と同じです。スタイルガイドでは『"""』が推奨されています。 |
| help(オブジェクト) | オブジェクトに付いたdocstringをコンソールに表示します。対話的環境でのドキュメント確認に使います。 |
| オブジェクト.__doc__ | docstringの文字列を直接参照する属性です。『None』の場合はdocstringが書かれていません。 |
サンプルコード
一行コメントの基本的な書き方と配置スタイルを確認します。
comment_style.py
# ブロックコメント: コードの上に書き、次の行の処理を説明します。
# 複数行にわたる場合は # を連続して書きます。
# ドラゴンボールの戦闘力データを定義します。
fighters = {
"孫悟空": 9000,
"ベジータ": 8500,
"フリーザ": 120000,
}
# 戦闘力が10000を超える戦士を抽出します。
powerful = {name: power for name, power in fighters.items() if power > 10000}
print("エリート戦士:", powerful) # インラインコメント: 行末に書く短い補足です。
# インラインコメントはコードから少なくとも2スペース空けます。
base_power = 5000 # ベース戦闘力
multiplier = 50 # 超サイヤ人倍率
final_power = base_power * multiplier # 変身後の戦闘力
print("変身後:", final_power)
python3 comment_style.py
エリート戦士: {'フリーザ': 120000}
変身後: 250000
関数にdocstringを付けて『help()』と『__doc__』で内容を確認します。
docstring_basic.py
def get_power_level(name, base, multiplier=1):
"""戦士の最終戦闘力を計算して返します。
ベースの戦闘力に倍率を掛けた値を返します。
multiplierを省略すると変身なしの戦闘力になります。
Args:
name (str): 戦士の名前。
base (int): ベースの戦闘力。
multiplier (int): 変身倍率。デフォルトは1(変身なし)。
Returns:
dict: name(名前)とpower(最終戦闘力)をキーに持つ辞書。
"""
return {"name": name, "power": base * multiplier}
# __doc__ 属性でdocstringを直接参照できます。
print(get_power_level.__doc__)
# help() でより見やすい形式で表示できます。
# help(get_power_level)
result = get_power_level("孫悟空", 9000, 50)
print(result["name"], "の戦闘力:", result["power"])
python3 docstring_basic.py
戦士の最終戦闘力を計算して返します。
ベースの戦闘力に倍率を掛けた値を返します。
multiplierを省略すると変身なしの戦闘力になります。
Args:
name (str): 戦士の名前。
base (int): ベースの戦闘力。
multiplier (int): 変身倍率。デフォルトは1(変身なし)。
Returns:
dict: name(名前)とpower(最終戦闘力)をキーに持つ辞書。
孫悟空 の戦闘力: 450000
Google・NumPy・reStructuredText の3つのdocstring形式を比較します。
docstring_styles.py
# Google スタイル: 読みやすくシンプルです。Google・TensorFlow系で広く使われます。
def charge_ki_google(fighter, amount, max_ki=100):
"""戦士の気を充填します(Google スタイル)。
Args:
fighter (str): 気を充填する戦士の名前。
amount (int): 充填する気の量。
max_ki (int): 気の上限値。デフォルトは100。
Returns:
int: 充填後の気の値。上限を超えた分はカットされます。
Raises:
ValueError: amountが0以下の場合に発生します。
"""
if amount <= 0:
raise ValueError("充填量は1以上でなければなりません")
return min(amount, max_ki)
# NumPy スタイル: 科学・数値計算系のライブラリで使われます。
def charge_ki_numpy(fighter, amount, max_ki=100):
"""戦士の気を充填します(NumPy スタイル)。
Parameters
----------
fighter : str
気を充填する戦士の名前。
amount : int
充填する気の量。
max_ki : int, optional
気の上限値。デフォルトは100。
Returns
-------
int
充填後の気の値。上限を超えた分はカットされます。
Raises
------
ValueError
amountが0以下の場合に発生します。
"""
if amount <= 0:
raise ValueError("充填量は1以上でなければなりません")
return min(amount, max_ki)
# reStructuredText スタイル: Sphinxドキュメント生成でよく使われます。
def charge_ki_rst(fighter, amount, max_ki=100):
"""戦士の気を充填します(reStructuredText スタイル)。
:param fighter: 気を充填する戦士の名前。
:type fighter: str
:param amount: 充填する気の量。
:type amount: int
:param max_ki: 気の上限値。デフォルトは100。
:type max_ki: int
:returns: 充填後の気の値。上限を超えた分はカットされます。
:rtype: int
:raises ValueError: amountが0以下の場合に発生します。
"""
if amount <= 0:
raise ValueError("充填量は1以上でなければなりません")
return min(amount, max_ki)
print(charge_ki_google("孫悟空", 80)) # 80
print(charge_ki_numpy("ベジータ", 150)) # 100(上限でカット)
print(charge_ki_rst("ピッコロ", 60)) # 60
python3 docstring_styles.py 80 100 60
クラスとモジュールレベルのdocstringを書きます。
class_docstring.py
"""ドラゴンボールの戦士を管理するモジュールです。
このモジュールはSaiyanクラスを提供します。
戦士の情報と変身管理を担当します。
"""
class Saiyan:
"""サイヤ人を表すクラスです。
サイヤ人の名前・戦闘力・変身状態を管理します。
Attributes:
name (str): サイヤ人の名前。
base_power (int): 変身前のベース戦闘力。
transformation (str): 現在の変身状態。
"""
def __init__(self, name, base_power):
"""Saiyanを初期化します。
Args:
name (str): サイヤ人の名前。
base_power (int): ベース戦闘力。
"""
self.name = name
self.base_power = base_power
self.transformation = "通常"
def transform(self, level):
"""超サイヤ人に変身します。
Args:
level (int): 変身レベル(1〜3)。
Returns:
str: 変身後のステータス文字列。
"""
multipliers = {1: 50, 2: 2500, 3: 4000}
multiplier = multipliers.get(level, 1)
power = self.base_power * multiplier
self.transformation = "超サイヤ人" + str(level)
return self.name + " [" + self.transformation + "] 戦闘力: " + str(power)
# クラスとメソッドのdocstringを確認します。
print(Saiyan.__doc__)
print("---")
goku = Saiyan("孫悟空", 9000)
print(goku.transform(1))
print(goku.transform(3))
python3 class_docstring.py
サイヤ人を表すクラスです。
サイヤ人の名前・戦闘力・変身状態を管理します。
Attributes:
name (str): サイヤ人の名前。
base_power (int): 変身前のベース戦闘力。
transformation (str): 現在の変身状態。
---
孫悟空 [超サイヤ人1] 戦闘力: 450000
孫悟空 [超サイヤ人3] 戦闘力: 36000000
型ヒントとdocstringの使い分けを確認します。型ヒントがあればdocstringの型記述を省略できます。
type_hints_vs_docstring.py
# 型ヒントなし: docstringに型情報を書きます(Google スタイル)。
def fuse(fighter1, fighter2, method):
"""2人の戦士を合体させます。
Args:
fighter1 (str): 合体する戦士1の名前。
fighter2 (str): 合体する戦士2の名前。
method (str): 合体方法("フュージョン" または "ポタラ")。
Returns:
str: 合体後の戦士の名前。
"""
return fighter1[:2] + fighter2[1:] + "(" + method + ")"
# 型ヒントあり: docstringから型情報を省略できます。
def fuse_typed(fighter1: str, fighter2: str, method: str) -> str:
"""2人の戦士を合体させます。
Args:
fighter1: 合体する戦士1の名前。
fighter2: 合体する戦士2の名前。
method: 合体方法("フュージョン" または "ポタラ")。
Returns:
合体後の戦士の名前。
"""
return fighter1[:2] + fighter2[1:] + "(" + method + ")"
print(fuse("孫悟空", "ベジータ", "フュージョン"))
print(fuse_typed("孫悟空", "ベジータ", "ポタラ"))
python3 type_hints_vs_docstring.py 孫悟ータ(フュージョン) 孫悟ータ(ポタラ)
よくあるミス
よくあるミス1: docstringの位置間違い
docstringは関数・クラス・モジュールの本体の先頭に書く必要があります。先頭以外の場所に書いた文字列はdocstringとして認識されず、『__doc__』属性はNoneになります。
ng_docstring_position.py
# NG: docstring が関数本体の先頭にありません。
def get_power_level(name, base):
result = base * 50
"""この文字列はdocstringではなく、ただの文字列リテラルです。"""
return result
print(get_power_level.__doc__)
python3 ng_docstring_position.py None
ok_docstring_position.py
# OK: docstring は関数本体の先頭に書きます。
def get_power_level(name, base):
"""戦士の変身後の戦闘力を計算して返します。"""
result = base * 50
return result
print(get_power_level.__doc__)
python3 ok_docstring_position.py 戦士の変身後の戦闘力を計算して返します。
よくあるミス2: 三重引用符の閉じ忘れ
三重引用符を閉じ忘れるとSyntaxErrorになります。複数行のdocstringを書く際に起きやすいミスです。
ng_unclosed_docstring.py
# NG: 三重引用符が閉じられていません。
def fuse(fighter1, fighter2):
"""2人の戦士を合体させます。
Args:
fighter1 (str): 合体する戦士1の名前。
fighter2 (str): 合体する戦士2の名前。
return fighter1[:2] + fighter2[1:]
python3 ng_unclosed_docstring.py
File "ng_unclosed_docstring.py", line 9
return fighter1[:2] + fighter2[1:]
^
SyntaxError: EOF while scanning triple-quoted string literal
ok_unclosed_docstring.py
# OK: 三重引用符をきちんと閉じます。
def fuse(fighter1, fighter2):
"""2人の戦士を合体させます。
Args:
fighter1 (str): 合体する戦士1の名前。
fighter2 (str): 合体する戦士2の名前。
"""
return fighter1[:2] + fighter2[1:]
print(fuse("孫悟空", "ベジータ"))
python3 ok_unclosed_docstring.py 孫悟ータ
よくあるミス3: 型ヒントとdocstringの型が食い違う
型ヒントとdocstringの型記述が矛盾していると、ツールの静的解析や読み手の混乱を招きます。型ヒントを追加・変更したらdocstringの型記述も同時に更新します。
ng_type_mismatch.py
# NG: 型ヒントは int だが、docstring は str と書いています。
def get_rank(score: int) -> str:
"""スコアからランクを返します。
Args:
score (str): スコア(文字列)。 # 型ヒントと矛盾しています。
Returns:
int: ランク文字列。 # 型ヒントと矛盾しています。
"""
return "S" if score >= 90 else "A"
python3 ng_type_mismatch.py
ok_type_mismatch.py
# OK: 型ヒントと docstring の型記述を一致させます。
# 型ヒントがある場合は docstring から型記述を省略することもできます。
def get_rank(score: int) -> str:
"""スコアからランクを返します。
Args:
score: スコア(0〜100の整数)。
Returns:
ランクを表す文字列("S", "A", "B", "C" のいずれか)。
"""
if score >= 90:
return "S"
elif score >= 80:
return "A"
elif score >= 70:
return "B"
return "C"
print(get_rank(85))
python3 ok_type_mismatch.py A
概要
コメントは『#』で書きます。コードの「何をするか」ではなく「なぜそうするか」を書くのが有益なコメントです。自明なコードへのコメントは冗長になる場合があります。インラインコメントはコードから2スペース以上空けて書くのがPEP 8のスタイルです。
docstringはモジュール・クラス・関数の先頭に置く特別な文字列リテラルで、『__doc__』属性としてアクセスできます。『help()』関数はこの属性を整形して表示します。Sphinxなどのドキュメント生成ツールもdocstringを自動的に読み取るため、ライブラリを作る際はdocstringを書くのが一般的です。
Google・NumPy・reStructuredText の3形式はどれを選んでもかまいませんが、プロジェクト内で統一することが重要です。型ヒント(『->』や引数の『: 型』)を使う場合、docstringへの型の重複記載は省略できます。型ヒントとdocstringは補完関係にあり、型ヒントが「何の型か」を、docstringが「何を意味するか」を伝えます。型ヒントの詳細はdef / 関数定義も参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。