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

Python3.0以降では関数アノテーション(Function Annotations)という仕組みによって、関数の引数や返り値にアノテーション(注釈)となる式を記述することができます。

PEP 3107 -- Function Annotations | Python.org 8. 複合文 (compound statement) 関数定義 — Python 3.6.5 ドキュメント

さらに、関数アノテーションに型情報を書く場合(型アノテーション)の記述方法がPEP484で規定され、それを実現するためにPython3.5で暫定的に標準ライブラリにtypingモジュールが追加されました。

PEP 484 -- Type Hints | Python.org 26.1. typing — 型ヒントのサポート — Python 3.6.5 ドキュメント

ここでは以下の内容について説明します。

関数アノテーションの書き方 __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)ではアノテーション(注釈)に何を書くかは定義されていません。

PEP 3107 -- Function Annotations | Python.org

PEP484で関数アノテーションに型を書く場合(型アノテーション)の標準の記述方法が新たに規定され、それを実現するためにPython3.5で暫定的に標準ライブラリにtypingモジュールが追加されました。

PEP 484 -- Type Hints | Python.org 26.1. typing — 型ヒントのサポート — Python 3.6.5 ドキュメント

あくまでも「型をアノテーションとして書く場合にはこのように書きましょう」という規定であって、型アノテーションを書くことは必須ではなく、型以外の情報をアノテーションとして書くことも認められています。 また、上述のようにアノテーションはただの注釈に過ぎないので、型ヒントを利用するライブラリや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)などが使えます。

Last Updated: 6/26/2019, 10:34:03 PM