Pythonの関数アノテーションと型ヒント、typingモジュール
Python3.0以降では関数アノテーション(Function Annotations)という仕組みによって、関数の引数や返り値にアノテーション(注釈)となる式を記述することができる。
- PEP 3107 -- Function Annotations | Python.org
- 8. 複合文 (compound statement) 関数定義 — Python 3.6.5 ドキュメント
さらに、関数アノテーションに型情報を書く場合(型アノテーション)の記述方法がPEP484で規定され、それを実現するためにPython3.5で暫定的に標準ライブラリにtypingモジュールが追加された。
ここでは以下の内容について説明する。
- 関数アノテーションの書き方
__annotations__
属性- 型ヒント(Type Hints)と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: 'description-x', y: 'description-y') -> 'description-return':
return x * y
print(func_annotations('abc', 3))
# abcabcabc
print(func_annotations(4, 3))
# 12
デフォルト引数はアノテーションのあとに記述する。
def func_annotations_default(x: 'description-x', y: 'description-y' = 3) -> 'description-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やエディタもある。
__annotations__
属性
関数アノテーションは__annotations__
属性に辞書(dict
型オブジェクト)として格納されている。
引数に対するアノテーションは辞書のキーが引数名、返り値に対するアノテーションはキーが'return'
となる。
def func_annotations(x: 'description-x', y: 'description-y') -> 'description-return':
return x * y
print(type(func_annotations.__annotations__))
# <class 'dict'>
print(func_annotations.__annotations__)
# {'x': 'description-x', 'y': 'description-y', 'return': 'description-return'}
print(func_annotations.__annotations__['x'])
# description-x
型ヒント(Type Hints)
PEP3107の関数アノテーション(Function Annotations)ではアノテーション(注釈)に何を書くかは定義されていない。
PEP484で関数アノテーションに型を書く場合(型アノテーション)の標準の記述方法が新たに規定され、それを実現するためにPython3.5で暫定的に標準ライブラリにtypingモジュールが追加された。
あくまでも「型をアノテーションとして書く場合にはこのように書きましょう」という規定であって、型アノテーションを書くことは必須ではなく、型以外の情報をアノテーションとして書くことも認められている。
また、上述のようにアノテーションはただの注釈に過ぎないので、型ヒントを利用するライブラリやIDE、エディタなどを使わない限り型チェックなどは行われない。
typingモジュールを利用すると、例えば以下のように型アノテーションを書ける。リストの要素の型の指定や、複数の型のいずれかといった指定が可能になった。
from typing import Union, List
def func_u(x: List[Union[int, float]]) -> float:
return sum(x) ** 0.5
print(func_u([0.5, 9.5, 90]))
# 10.0
List[X]
: 要素の型がX
のリスト(list
)Union[X, Y]
:X
かY
いずれかの型
そのほかにも、
Any
: 任意の型Callable[[X ...], Y]]
: 引数の型のリストが[X ...]
、返り値の型がY
の呼び出し可能オブジェクトDict[X, Y]
: キーの型がX
, 値の型がY
の辞書(dict
)
などが使える。