概要
PEP 484: Type Hints がPython3.5で導入されました。詳しくは、公式ドキュメント 型ヒントのサポート を参照してください。
最近、コミュニティ内でも導入している話を多く聞くようになりました。私も今後のプロジェクトで導入を進めたいと思い、自身の勉強と他の人に説明するときの参考資料にするためにここにまとめます。
型ヒントは、Pythonの文法としてPython3.5以降で導入されました。
- ヒントなので、実行時には何も影響を与えない
- 組み込みの公式ツールはない
ツール
- mypyというデファクトのチェックツールがある(pipでインストール可能)
- PyCharmなどのエディタが対応し、コード補間が強力になり、チェックもしてくれる
- ヒントを記載した場所(モジュール単位でも関数単位でも)のみで有効になる
- ヒント書けば書くほどコード補間が効き、チェックもしてくれる
mypyのインストール
(env) $ pip install mypy
mypyでチェック
(env) $ mypy モジュール名
型ヒント定義例
例として、すべて整数(int)型で示します。
変数定義
a: int = 10
a: int
a = 10
関数の引数定義
def f(a: int):
pass
def f(a: int = 10):
pass
関数の戻り値定義
def f(a) -> int:
return 10
def f(a: int, b: int = 10) -> int:
return a + b
型定義
データ型で定義
名称 | 型 |
---|---|
整数 | int |
浮動小数点数 | float |
文字列 | str |
バイト型 | bytes |
真理値 | bool |
None | None |
コンテナ系
コンテナ系は、内包する型を指定するので、 list[int]
などと表記を行いたい。しかし、これはPythonの文法エラーとなってしまう。その為に、typingでは専用の型を準備している
from typing import List, Tuple, Dict, Set
名称 | 型 | 定義例 |
---|---|---|
リスト | List | List[int] |
タプル | Tuple | Tuple[int, int] / Tuple[int, ...] |
辞書 | Dict | Dict[str, int] |
セット | Set | Set[int] |
特殊な型
from typing import Any
名称 | 型 | 定義例 |
---|---|---|
なんでもいい | Any | Any |
from typing import Callable, Iterator, MutableMapping
名称 | 型 | 定義例 |
---|---|---|
呼び出し可能 | Callable | Callable[[int, float], bool] |
繰り返し可能 | Iterator | Iterator[int] |
辞書のような挙動 | MutableMapping | MutableMapping[str, int] |
その他
Optional
Optionalは、指定の型 or Noneを、許容する型です。
例えば、整数とNoneのいずれかを許容する場合は、 Optional[int]
とします。
以下の様なケースで利用します。
from typing import Optional
def f1(a: int, b: int) -> Optional[int]:
if b == 0:
return None
return a // b
便利なのは以下の様に使えるからです。
def f2(c: Optional[int]) -> int:
if c is None:
c = 0
return c + 100
上記のケースを以下の様に記載すると、mypyがエラーを通知します。
def f2(c: Optional[int]) -> int:
return c + 100
$ mypy sample.py
sample.py:**: error: Unsupported operand types for + ("None" and "int")
sample.py:**: note: Left operand is of type "Optional[int]"
Found 1 error in 1 file (checked 1 source file)
つまり、 if c is None
を行うことで、cがNoneの時を加え、それによりそれ以降の行では、変数c
は、整数型(int)であることが確定しているので、問題なく処理ができることを保証しています。
Union
Unionは、2つのいずれかの型を示すことができます。
例えば、整数型 or 文字列型 と言った場合に、 Union[int, str]
と指定します。
以下の様に引数を受け取るときに、整数か文字列かが分からないような場合に使い、 isinstance
を使って処理を分けることで、上記のOptional同様に、変数の型を確定させる事ができます。
from typing import Union
def f3(d: Union[int, str]) -> str:
if not isinstance(d, str):
d = str(d)
return d.upper()
ここでは、 if not isinstance(d, str):
として、変数dが文字列型(str)でないときに、文字列に変換する処理を入れて処理を継続しています。 return d.upper()
で、 d
が文字列であることが分かっているので、安全に大文字に変換する文字列型のメソッドが使えています。
int と float
intと指定してfloatは入れられませんが、その反対のfloatと指定してintを入れる事ができます。
以下の場合、 num4だけがエラーがでます。
num1: float = 1.0
num2: float = 1
num3: int = 1
num4: int = 1.0 # これはエラーとなる
$ mypy sample/sample.py
sample.py:**: error: Incompatible types in assignment (expression has type "float", variable has type "int")
これは、intをfloatに自動変換することができるが、その反対のfloatをintにすると情報を失うことがあることに起因しているそうです。