TSUBOCK★LABO-ツボックラボ-

とあるセキュリティエンジニアの技術メモブログ

MENU

Type Hintsを使ってPythonの型を明示的に宣言してみよう。

Pythonは動的型付言語であるため、JavaやC言語のように変数に対して型を宣言する必要はないため、処理の中で型を操作するためには前後の処理を見て「こっちはString型」「こっちはInteger型」「あっちはDate型」と判断することが多いかもしれません。Pythonの3.5からType Hintsという仕様が追加されました。

Type Hintsとは

Type HintsはPEP484で提案された静的解析を行うための仕様です。Type Hintsを設定することにより、関数の引数や戻り値に定義した型が正しく使われているかのチェックを行うことができます。Type Hintsは必須定義ではないので、必ずしもType Hintsを守らずに型を定義しなくても動かすことはできます。プログラムの可読性やメンテナンス性を向上させるために使います。

Type Hintsを使ってみる

Type Hintsを使うときにはTypingをimportして使用します。

型の定義の仕方は

{変数名}: {型}
または
{変数名}: {型} = {初期値}

という書き方で指定します。

例えば、下記のようなPythonプログラムがあったとします。

A = 1
B = 2
def test(A, B):
    return A + B
    
print(test(A, B))

上記は、testの引数にどんな型の値が入ってきても問題ありません。

Type Hintsで型定義をするとこんな感じです。

A = 1
B = 2
def test(A: int, B: int):
    return A + B

print(test(A, B))

def test(A: int, B: int):でAとBにはint型で入ってくることを定義しています。

定義しておくことで、自分または他の人がソースコードレビューをするときに、test関数を呼び出すときにどんな型の変数が必要なのかが明示的にわかるので、可読性の向上につながります。

初期値を指定する場合は下記のような形です。

A = 1
B = 2
def test(B: int, A: int = 1):
    return A + B

print(test(A, B))

testを呼び出すときにAに1が入っていることを明示的に定義しています。後ほど登場する静的チェックを行ったときに、test関数を呼び出すときの変数が想定している変数なのかをチェックすることができます。

上記で引数の各順番を変えていますが、引数でデフォルト値を宣言したい場合で、デフォルト値を宣言しないものと宣言するものを混ぜる場合は、デフォルト値を宣言しない引数よりも後に書かないと、下記のように実行時にエラーメッセージが表示されます。

$ python3 test.py
  File "test3.py", line 3
    def test(A: int = 1 , B: int) -> int :
            ^
SyntaxError: non-default argument follows default argument

関数の戻り値の型も明示的に下記のように表すことができます。

A = 1
B = 2
def test(A: int, B: int) -> int:
    return A + B

print(test(A, B))

-> {型}をつけることで、明示的に宣言することができます。

Type Hintsはプログラム対して制限をかけることはできません。例えば、下記のように引数や戻り値が想定していない型で出入りした場合でもPythonプログラムとしては問題なく動作してしてしまいます。

A = 1
B = 2
def test(A: str, B: int) -> int:
    return A + B

print(test(A, B))
  • 実行結果
$ python test.py
3
# エラーにならない!!

mypyでさらに便利に

Type Hintsで型を静的に宣言するとmypyというライブラリでType Hintsで定義された型が正しく使われているか静的チェックすることができます。

インストール

$ pip install mypy

mypyを使う

先ほどの引数にstr型を指定した下記のプログラムに対してmypyで静的チェックをかけてみます。

A = 1
B = 2
def test(A: str, B: int) -> int:
    return A + B

print(test(A, B))

実行結果

$ mypy test.py
test4.py:4: error: Unsupported operand types for + ("str" and "int")
test4.py:6: error: Argument 1 to "test" has incompatible type "int"; expected "str"
Found 2 errors in 1 file (checked 1 source file)

このように静的宣言した箇所について、mypyが静的チェックをかけてエラーを出力してくれます。

型宣言が正しいソースコードを静的チェックかけた場合には、

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

静的チェックで問題ないことが確認できます。

単体テストをかける前にmypyを使って適宜型チェックを行う癖をつけると、可読性を向上させて手戻りの少ないプログラムが書けるのではないでしょうか。

参照:

PEP484

実践!!Python型入門(Type Hints) - Qiita

mypyやっていくぞ - Qiita