Pythonの関数アノテーションと型ヒント、typingモジュール

Modified: | Tags: Python

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

さらに、関数アノテーションに型情報(型アノテーション)を書く場合の記述方法が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]XYいずれかの型、Anyは任意の型を表す。

Python 3.10以降はUnionではなく|演算子を使うこともできる。

def func(x: int | float) -> float:
    return x * 0.5

そのほかにも、引数の型のリストが[X ...]、返り値の型がYの呼び出し可能オブジェクト(関数など)を表すCallable[[X ...], Y]]などもある。詳細は公式ドキュメントを参照。

関連カテゴリー

関連記事