Python3.xの型チェック

Python3.5以降での型チェックの方法の紹介


Pythonの型

ご存じのようにPythonは型に柔軟な言語で、例えば

def add_any(x, y):
    return x + y

上記の関数は、整数型でも浮動小数点型でもList型でも動作します

>>> print(add_any(1, 2))
3
>>> print(add_any(1.2, 2.3))
3.5
>>> print(add_any([1], [2]))
[1, 2]

もちろんこれは便利なことも多いですが、コードのバグの発見を遅らせるなどの弊害もあると思います


Type Hint

Python3.5以降では、変数や関数の引数にType情報を付加できるようになりました

例えば

def add_int(x: int, y: int):
    return x + y

ただしこれは”ヒント“を与えているだけで、実際の動作には影響しません

>>> print(add_int(1.2, 2.3))
3.5
>>> print(add_int([1, 2], [3]))
[1, 2, 3]

このようにfloatlistを与えてもadd_any()と同様に動作します。あくまでType情報は属性を設定しているだけであり、それをチェックするには別のサードパーティツールを使用する必要があります


静的チェックツール

スクリプトを実際に実行せずに静的に型をチェックするツールとしてはPyCharmの型チェック機能とスタンドアローンツールのmypyが有名なようです。ここではmypyを例に説明します

mypyのインストール

% pip install mypy

mypyの実行

% mypy test.py
test.py:15: error: Argument 1 to "add_int" has incompatible type "float"; expected "int"
test.py:16: error: Argument 1 to "add_int" has incompatible type "List[int]"; expected "int"
test.py:16: error: Argument 2 to "add_int" has incompatible type "List[int]"; expected "int"
Found 3 errors in 1 file (checked 1 source file)

動的チェックツール

pipでインストール可能なtypeguardというツールを紹介します

Typeguardのインストール

% pip install Typeguard

Typeguardの使い方

型チェック
from typeguard import typechecked

@typechecked
def add_int(x: int, y: int):
    return x + y
>>> print(add_int(1.2, 2))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:/pyinstall/lib/python3.8/site-packages/typeguard/__init__.py", line 839, in wrapper
    check_argument_types(memo)
  File "C:/pyinstall/lib/python3.8/site-packages/typeguard/__init__.py", line 700, in check_argument_types
    raise exc from None
  File "C:/pyinstall/lib/python3.8/site-packages/typeguard/__init__.py", line 698, in check_argument_types
    check_type(description, value, expected_type, memo)
  File "C:/pyinstall/lib/python3.8/site-packages/typeguard/__init__.py", line 620, in check_type
    raise TypeError(
TypeError: type of argument "x" must be int; got float instead
>>> print(add_int([1], [2]))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:/pyinstall/lib/python3.8/site-packages/typeguard/__init__.py", line 839, in wrapper
    check_argument_types(memo)
  File "C:/pyinstall/lib/python3.8/site-packages/typeguard/__init__.py", line 700, in check_argument_types
    raise exc from None
  File "C:/pyinstall/lib/python3.8/site-packages/typeguard/__init__.py", line 698, in check_argument_types
    check_type(description, value, expected_type, memo)
  File "C:/pyinstall/lib/python3.8/site-packages/typeguard/__init__.py", line 620, in check_type
    raise TypeError(
TypeError: type of argument "x" must be int; got list instead

おすすめ