名古屋出身ソフトウェアエンジニアのブログ

Mypy による型チェック入門

公開:
更新:

元所属していた研究室の方が Mypy を使っているのを観測し、今はどの程度使えるようになっているのか、使用感などを体験してみることにしました。

Mypy の導入と使い方

pip でも conda でも簡単にインストールできます。

pip3 install mypy
conda -c conda-forge install mypy

使い方も簡単で、基本的にはエントリになっているスクリプトファイルを指定しておけば、インポートしているモジュールも含めてチェックしてくれます。

mypy main.py

あるいはソースディレクトリを指定すると、中のファイルを再帰的にチェックできます。

mypy ./src/

実際に型チェックしてみる

単純なパラメータ多相のスタッククラスを定義しました。Generic を継承して、初期化時に指定する型パラメータの値のみ push/pop 操作できるよう型注釈されています。

使用例では、型パラメータを int とし、10 を push しています。

from typing import TypeVar, Generic

T = TypeVar("T")

class MyStack(Generic[T]):

    def __init__(self) -> None:
        super().__init__()
        self.items: list[T] = []

    def push(self, item: T) -> None:
        self.items.append(item)

    def pop(self) -> T:
        if self.items:
            return self.items.pop()
        else:
            raise IndexError("pop from empty stack")

# 使用例
s = MyStack[int]()
s.push(10)
print(s.pop())  # 10

このファイルを Mypy に渡します。

$ mypy main.py
Success: no issues found in 1 source file

想定通りにきちんと型が付いていました。

エラーを起こしてみる

わざとエラーを起こしてみます。

int を受け入れるスタックに str を push する誤った使い方をコーディングしてみます。

s = MyStack[int]()
s.push("aaa")
print(s.pop())

Mypy によって型エラーがきちんと捕捉されました。

$ mypy main.py
main.py:21: error: Argument 1 to "push" of "MyStack" has incompatible type "str"; expected "int"  [arg-type]
Found 1 error in 1 file (checked 1 source file)

このように「普通の」プログラムであれば、かなり使える段階まで Mypy は来ているなと感じました。