Pythonの関数アノテーションと型ヒント、typingモジュール
Python3.0から、関数アノテーション(Function Annotations)という仕組みによって、関数の引数や返り値にアノテーション(注釈)を記述できるようになった。
- PEP 3107 – Function Annotations | peps.python.org
- 8. 複合文 (compound statement) - 関数定義 — Python 3.12.0 ドキュメント
さらに、関数アノテーションに型情報(型アノテーション)を書く場合の記述方法がPEP 484で規定され、それを実現するためにPython3.5で標準ライブラリにtypingモジュールが追加された。
関数の説明はdocstringに記述することもできる。詳細は以下の記事を参照。
関数アノテーションとdocstringは二者択一ではなく、型は関数アノテーション、詳しい説明文はdocstringというように併用して記述する場合も多い。
関数アノテーションの書き方: :
, ->
通常の関数
アノテーションを含まない通常の関数は以下のように書く。
def func(x, y):
return x * y
print(func('abc', 3))
# abcabcabc
print(func(4, 3))
# 12
関数アノテーション
関数アノテーションは以下のように記述する。
引数名のあとの: 式
がそれぞれの引数に対するアノテーション、括弧と末尾のコロン:
の間の-> 式
が返り値に対するアノテーションとなる。アノテーションを記述するものと記述しないものが混在していても問題ない。
関数としての使い方は通常の関数と同じ。
def func_annotations(x: 'for_x', y: 'for_y') -> 'for_return':
return x * y
print(func_annotations('abc', 3))
# abcabcabc
print(func_annotations(4, 3))
# 12
デフォルト引数はアノテーションのあとに記述する。
def func_annotations_default(x: 'for_x', y: 'for_y' = 3) -> 'for_return':
return x * y
print(func_annotations_default('abc'))
# abcabcabc
print(func_annotations_default(4))
# 12
関数アノテーションはあくまでもただの注釈
関数アノテーションはあくまでも引数や返り値に対する注釈で、それをもとに特別な処理が行われることはない。
例えば、アノテーションとして型を指定することもできるが、実行時に型チェックが行われたりはしないのでアノテーションで指定した型ではない値を渡しても何も起こらない(エラーにならない)。
def func_annotations_type(x: str, y: int) -> str:
return x * y
print(func_annotations_type('abc', 3))
# abcabcabc
print(func_annotations_type(4, 3))
# 12
PyCharmなど、アノテーションをもとに静的解析を行って警告を出したりしてくれるIDEやエディタもある。また、型チェックを行うためのライブラリとしてmypyがある。
__annotations__
属性
関数アノテーションは__annotations__
属性に辞書(dict
)として格納されている。
引数に対するアノテーションは辞書のキーが引数名、返り値に対するアノテーションはキーが'return'
となる。
def func_annotations(x: 'for_x', y: 'for_y') -> 'for_return':
return x * y
print(type(func_annotations.__annotations__))
# <class 'dict'>
print(func_annotations.__annotations__)
# {'x': 'for_x', 'y': 'for_y', 'return': 'for_return'}
print(func_annotations.__annotations__['x'])
# for_x
型ヒント(Type Hints)とtypingモジュール
PEP 3107の関数アノテーション(Function Annotations)ではアノテーションに何を書くかは定義されていない。
PEP 484で関数アノテーションに型情報(型アノテーション)を書く場合の標準の記述方法が新たに規定され、それを実現するためにPython3.5で標準ライブラリにtypingモジュールが追加された。
あくまでも「型をアノテーションとして書く場合にはこのように書きましょう」という規定であって、型アノテーションを書くことは必須ではなく、型以外の情報をアノテーションとして書くことも認められている。
また、上述のようにアノテーションはただの注釈に過ぎないので、型ヒントを利用するライブラリやIDE、エディタなどを使わない限り型チェックなどは行われない。型チェックを行うライブラリとしてはmypyがある。
変数アノテーション
PEP 526で、変数アノテーションが導入された。関数だけでなく変数定義(宣言)時に型アノテーションを記述できる。
i: int = 100
l: list[float] = [0.1, 0.2, 0.3]
d: dict[str, int] = {'a': 100, 'b': 200}
dict[X, Y]
はキーの型がX
、値の型がY
であることを表す。
list[]
やdict[]
が使えるようになったのはPython 3.9からなので注意。それより前のバージョンではtypingモジュールのList[]
やDict[]
を使う。
typingモジュールの使用例
typingモジュールを利用すると、例えば以下のように型アノテーションを書ける。
from typing import Union, Any
def func_union(x: Union[int, float]) -> float:
return x * 0.5
var: Any = 100
Union[X, Y]
はX
かY
いずれかの型、Any
は任意の型を表す。
Python 3.10以降はUnion
ではなく|
演算子を使うこともできる。
def func(x: int | float) -> float:
return x * 0.5
そのほかにも、引数の型のリストが[X ...]
、返り値の型がY
の呼び出し可能オブジェクト(関数など)を表すCallable[[X ...], Y]]
などもある。詳細は公式ドキュメントを参照。