Pythonでは、関数や変数の型を強制しない。ただ、IDEなどが参照するように型注釈を追加することはできる。この仕組みは型ヒントと呼ばれている。

Pythonにおける型注釈=型ヒント

プログラミング言語の中には、変数や関数・クラスの引数や返り値などに対して、期待する型を指定できるものがある。この仕組みは一般に型注釈(Type Annotation)と呼ばれる。

型注釈を導入すると、主に以下のようなメリットが得られる。

  • 互換性のない値によるバグの予防
  • 何を渡し、何を返すかが明示されることによる可読性の向上
  • エディタに型情報を伝えることによるオートコンプリート
  • ドキュメント生成ツールの補助

一方で、ソースが複雑になるというデメリットがある。そのため、型注釈を省略し、実行時にプログラムによって自動で型を確認するプログラミング言語も多い。

Pythonはこのタイプの言語だ。

とはいえ、型注釈のメリットは捨てがたい。そこで導入されたのが型ヒントである。

型ヒントに使う主な型

型ヒントには、任意の型を指定できる。ただ、Pythonの標準型はある程度覚えておかないと、型ヒントを使うメリットが半減してしまう。

以下に、使用頻度の高そうな型(というかドキュメントで目についた型)をまとめる。

もちろん、すべて覚える必要はない。必要に応じてドキュメントを参照し、覚えていけば良い。と自分を慰めておく。

ただ、Pythonの型注釈に関する情報はあっちこっちに散らばっていて追いかけるのが大変だ。変更される頻度も高そうである。個人的な感覚では、公式ドキュメントよりもmypyのドキュメントの方が体系化されていてわかり良い(mypyは、Pythonのデファクトスタンダードな静的型チェックツール)。

組み込み型

型ヒントの種類 型ヒントが示す内容
int 整数。
float 浮動小数点数。
complex 複素数(なんじゃこりゃあ)。
bool 真偽値。
list[型名] 配列([]で囲ったカンマ区切りの値)
tuple(型名1, 型名2, …) タプル(()で囲ったカンマ区切りの値)
range レンジ(range()の返り値)
str 文字列。''あるいは""で囲った値。
bytes バイト列。イミュータブル。
bytearray バイト列。ミュータブル。
memoryview バイト列。bytes、bytearrayを効率的に扱う。
set[型名] 集合型。{}で囲ったカンマ区切りのユニークな値。ミュータブル。
frozenset 集合型。イミュータブル。
dict[キーの型, 値の型] 辞書型。{}で囲ったキーバリューセット。 キーの型は基本str

listtuplesetは、他の型を引数に持つ。これはジェネリック型と呼ばれる。ジェネリック型は、ユーザーが任意に定義することもできる。

特殊な型

型ヒントの種類 型ヒントが示す内容
Any どんな値でもOK。
None 型ヒントとして使われる場合、Nonetype(None)と同じ。ちなみにPythonでは、return文のない関数は暗黙的にNoneを返す。
NoReturn 暗黙的にも明示的にも何も返さない関数(主にエラーを発生させる関数)。
Never NoReturnと同じ。NoReturnの意図を明確にするために、version 3.11で追加された。
type[クラス名] []の中に入れたクラスの派生クラス。

これらのうち、Nonetypeは何もインポートしなくても使える。ただしAnyNeverNoReturnは、typingモジュールからインポートする必要がある。

インポートが必要なものとそうでないものとの違いはよくわからない。

型エイリアス

型に別名がつけた方が可読性が向上するケースがある。この別名をつける仕組みは型エイリアスと呼ばれる。Pythonの型注釈システムはまだまだ発展途上の段階であるため、古い型もサポートしたい場合などにも型エイリアスは役立つ。

型エイリアスは、typeをつけて定義する。

python
type Point = tuple[float, float]

型ヒントの書き方

型ヒントの基本的な書き方は難しくない。変数や引数の型は:、返り値の型は関数名()の後ろに->をつけて指定する。

変数

変数名: 型 = 値という形。

python
number: int = 0
text: str = ''
boolean: bool = True
number_list: list[int] = [0, 1, 2]
# 複数の型を受け入れる場合は、`|`で区切る
int_or_none2: int | None = 0

関数

def 関数名(引数名: 型名) -> 型名:という形。

python
def introduce(name: str) -> None:
    print(f"My name is {name}!!")

クラス

クラスは、属性とメソッド、それぞれに型指定を追加する形で指定する。

python
class Person:
    first_name: str
    last_name: str

    def __init__(self, first_name: str, last_name: str) -> None:
        self.first_name = first_name
        self.last_name = last_name

    def introduce(self) -> None:
        print(f'My name is {self.last_name} {self.first_name}')

だいたい以上である。

わからないことだらけだ! ああああああぁぁぁ!!

叫んで奇天烈な踊りをしたらスッキリした。がんばれ私。

参照