[Python]型ヒント

Python

静的型付け言語からPythonにもどってくると、型を付けたほうが良いのかなと思うようになり、Pythonで型を注釈する方法をまとめます。

※Pythonでは3.5から型ヒントを使用できますが、このページではPython3.9以上の使用を想定しています。

参考ページ
typing --- 型ヒントのサポート — Python 3.11.3 ドキュメント

使用した環境
Windows10
Python 3.11.3

 Androidアプリを作成しました。
 感情用のメモ帳です。

スポンサーリンク
スポンサーリンク

型ヒントの付け方

型ヒントはおもに変数、関数の引数、戻り値に対してつけることができます。

付け方は次のような形です。

変数: 型名

def 関数(引数: 型名) -> 戻り値の型

num: int = 8
num_f: float = 4.6
st: str = "Python"
li: list[str] = ["a", "b", "c"]
tu: tuple[str, int, str] = ("1", 2, "3")
di: dict[str, str] = {"Japan": "Tokyo", "China": "Beijing"}
se: set[int] = {3, 5, 7, 9}

def five_times(n: int) -> int:
    return n * 5

型をチェックする方法

型をチェックするPythonの標準ライブラリや公式のツールはありません。

現状(2023)ではサードパーティ製の「mypy」が広く使われています。

pip install mypy

インストール後、mypyにファイルを渡します。

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

型ヒントをつけるメリット

ざっと思いつくメリットは3つあります。

  1. 可読性の向上
  2. ミスを減らす
  3. IDEやエディタでの補完が効く

1は説明するまでもないでしょう。

2に関して具体例を示すため、上の項目で出した関数をもう一度、掲載します。

def five_times(n: int) -> int:
    return n * 5

print(five_times("5"))

指定している型と実際に渡した型は違っていますが、Pythonの文法上は問題ありませんから、実行してもエラーにはなりません。

$ py typing1.py 
55555

短いコードですし、結果を出力しているため、ミスにはすぐ気づくかもしれませんが、これが長いコードや結果を見ないような場合はそうではないかもしれません。

$ mypy typing1.py 
typing1.py:4: error: Argument 1 to "five_times" has 
incompatible type "str"; expected "int"  [arg-type] 
Found 1 error in 1 file (checked 1 source file)

型をチェックすることでミスの早期発見・削減につながります。

3が個人的には一番の理由ですが、使用するIDEやエディタによっては補完が効くようになります。

次の画像はVisual Studio Codeでの様子です。
型を付けない場合、この段階では「s」の型が分からないため補完が効いていません。

引数sに対して補完が効かない

型を注釈することで文字列のメソッドの候補が表示されます。

引数sに対して補完が機能している

ユースケース

異なる型の許容

複数の型の可能性がある場合、typingのUnionをインポートし、複数の型を注釈することができます。

from typing import Union


def five_times(n: Union[int, str]) -> Union[int, str]:
    return n * 5

Python3.10以上なら、記号「|」を使って書くこともできます。
※インポートは不要

def five_times(n: int | str) -> int | str:
    return n * 5

何にでも適合するAny型、というのもあります。
※インポートが必要

from typing import Any


def five_times(n: Any) -> Any:
    return n * 5

ただし、この場合は注釈しないことと同義です。

リストで異なる型を許容するには、上記と同じようにUnionを使用します。

固定長で変更しなくても良いならタプルも使えます。

クラス

クラスの初期化メソッド「__init__」を介してメンバ変数に型の注釈を行います。

class Gorilla:
    def __init__(self, age: int, home: str) -> None:
        self.age = age
        self.home = home


shabani = Gorilla(27, "Higashiyama")

dataclassesdataclassをデコレータとして使うと、次のように書くこともできます。

from dataclasses import dataclass


@dataclass
class Gorilla:
    age: int
    home: str


shabani = Gorilla(27, "Higashiyama")

個人的にはこちらの方が見やすいですね。

タイトルとURLをコピーしました