note.nkmk.me

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

Date: 2018-06-20 / tags: Python
このエントリーをはてなブックマークに追加

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

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

そのほかにも、

  • Any: 任意の型
  • Callable[[X ...], Y]]: 引数の型のリストが[X ...]、返り値の型がYの呼び出し可能オブジェクト
  • Dict[X, Y]: キーの型がX, 値の型がYの辞書(dict

などが使える。

スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事