背景
機械学習とか画像処理とか, numpy を使う場合型はだいたい既知(e.g. 画像データだと dtype np.uint8
とか)なので, 静的型チェックしたい.
Python3.5 以降の型アノテーション + mypy + nptyping
(完全ではない) を使います.
(numpy v1.12 かそれ以降では numpy.typing
が使えるようだが現状 2021/01/28 時点では v1.12 はベータリリース段階で stable release は v1.19)
Python 3.8 以降あたりを使うのがよさそうです.
ただ, 現状(2021/01/28 時点), 完全にうまく行く方法はありません.
(追記) 2021/01/30 に numpy.typing
対応した numpy v1.20 がリリースされました.
今後はこちらを mypy と共に使うのが主流になっていくことでしょう.
静的型チェック
- 型アノテーションと実行時型チェックをコードに記述
- mypy でチェック
- OK になったら普通に python で実行
のステップになります.
mypy とは...?
Pythonではじまる、型のある世界
https://qiita.com/icoxfog417/items/c17eb042f4735b7924a3
ありがとうございます.
ただ, そのまま mypy 実行だと numpy
module の型情報取得できないっぽいので,
Type hint for NumPy ndarray dtype?
https://stackoverflow.com/questions/54503964/type-hint-for-numpy-ndarray-dtype
にあるように, data-science-types
を入れておきます(ついでに pandas
とかでも使えてよい)
他に使っている module があり型ヒントがなくてエラーになる場合は, 適当に --ignore-missing-imports
をつけるなりしてひとまず suppress しておきます.
nptyping で型アノテーション
numpyでも型ヒントチェックしたいと思った
https://qiita.com/qython/items/1f7416bbb29f48a153bb
ありがとうございます.
nptyping なしで文字列指定もできますが, dtype のチェックはうまくしてくれないようで
import numpy as np
def proc_numpy(a: "np.ndarray[np.float64]"):
print(a)
a = "bora"
proc_numpy(a) # error
b = np.random.rand(4, 5).astype(np.int32)
proc_numpy(b) # ok :thinking:
文字列渡す場合は
error: Argument 1 to "proc_numpy" has incompatible type "str"; expected "ndarray[float64]"
とエラーレポートしてくれますが,
と int 配列を渡す場合は mypy は OK をレポートしてしまいます.
nptyping を使って型アノテーションを書くと, size や dtype もチェックできまます.
nptyping は mypy でチェックできない
しかし, 現状 nptyping
は残念ながら mypy でサポートしていないため,
def proc_numpy(a: NDArray[(typing.Any, ...), Float[64]]) -> None:
print(a)
のように書いても mypy チェックでは無視されます
関数の引数の型指定の場合, ひとまずは文字列指定などで最低限のチェックを mpypy で行い,
残りは isinstance
で実行時型チェックするかありません.
実行時型チェック
上記のようなケースや, コードの書き方によっては実行時にチェックする必要も出てくるかと思います.
実行時に型チェックしたい場合は今までどおり assert isinstance(...)
あたりを記載することになるかと思います.
(将来) numpy.typing で型アノテーション
v1.12 では numpy 自体に取り込まれるっぽい.
まとめ
numpy.typing
にいずれは統合されて mypy でよろしく型チェックできると思われますが, python 自体の型サポートとあいまり, 現状は過渡期という感じです.
python 3.10+ + numpy v1.12+ あたりでいい感じになるかもしれません.