関数アノテーションと型ヒント,変数アノテーション,docstring
「あれ?この関数の引数と戻り値なんだったっけ…(´Д` ;)」
という事態にしばしば陥ったため,戒めのためにメモ.
関数アノテーション(function annotations)
普通,Pythonでは関数は次のように書く.
def func(x, y): return x + y
pythonは動的型付け言語であるため,x
とかy
の型は指定されていない.
これにより,コードが楽に書ける一方で,コードを書いた本人ですら,引数や戻り値の型を後で忘れてしまって大混乱,という事態になりかねない.
そこで,Python3.0以降,次のように注釈(アノテーション)をつけることができるようになった.
def func(x: "int", y: "int") -> "int": return x + y
このように注釈をつけても,関数の機能にはなんら影響を与えないし,x
やy
にstr型の値を代入してもエラーにはならない.
次のように自由に注釈がつけられる.
def func(x: "ご当地キャラ", y: "悪魔") -> "くまモン": return x + y
単に,コードを読む人に対してわかりやすくなる,という以上の効果はない.
型ヒント(type hints)
上の書き方だと自由に注釈を書くことができたけど,PEP484で標準の記述方法が規定された.
例えば次のようにも書けるようになった.
def func(x: int, y: int) -> int: return x + y
from typing import List def sum_func(x: List[float]) -> float: return sum(x)
記述できる型としては
- int
- float
- str
- bool
- complex
などが使える.
また,Python3.5以降で追加されたtypingモジュールを利用することにより,以下のような型アノテーションが書けるようになる:
- List[X]: 要素がXという型からなるリスト
- Dict[X, Y]: キーがX, 値がYという型からなる辞書
- Tuple[X, Y]: 要素がX, Yという型からなるタプル
- Union[X, Y]: XかYの型
- Any: 任意の型
あくまで注釈なので,これらを書いても型のチェックは行われない.
変数アノテーション(variable annotations)
変数に対しても型ヒントとかGolang的な書き方がしたい場合,
a: int = 100
のような書き方がPython3.6以降できるようになった.
ただし,これも型チェックがされるわけではないので,
b: str = 100
のように書いても,相変わらずpythonは型を自動的に推定してb
の型はintだと認識するので注意.
np.arrayの場合どうしよう?
一応,
c: np.ndarray = np.array([1,2,3])
のように変数アノテーションをつけることはできる.
docstringに書けばいいじゃない
Pythonでは,関数やクラスなどの記述の,先頭の文字列はdocstring(ドキュメンテーション文字列)として扱われ,これを後でsphinxなどで文書化して仕様書を自動生成,という素晴らしい手順もあります.
- reStructuredText(reST)スタイル
- NumPyスタイル
- Googleスタイル
の中でも,たとえばGoogleスタイルで注釈を書くと,
def func_google(arg1, arg2): """関数の説明 Args: arg1 (int): 引数arg1の説明 arg2 (str): 引数arg2の説明 Returns: bool: 戻り値の説明 """ return True
のようになる.
docstringは,その関数の__doc__
に保存されている:
print(func_google.__doc__)
関数の説明 Args: arg1 (int): 引数arg1の説明 arg2 (str): 引数arg2の説明 Returns: bool: 戻り値の説明
ここまで書けば,関数アノテーションを使う必要はないだろう.
変数アノテーションと組み合わせて,リーダブルかつデバッグしやすいコードを心がけたい.
参考にさせていただいたページ
Pythonの関数アノテーションと型ヒント、typingモジュール | note.nkmk.me
26.1. typing — 型ヒントのサポート — Python 3.6.5 ドキュメント