Pythonはもともと「動的型付け言語」として知られ、変数の型を宣言せずに自由にコードを書ける手軽さが魅力です。
しかし、プロジェクトの規模が大きくなるにつれて、「この関数の引数は何を受け取るんだっけ?」「実行してみないとエラーがわからない」といった動的型付け特有の悩みに直面することも少なくありません。
完全に静的な言語(JavaやC#など)になるわけではありませんが、コードに型の情報を付与することで、可読性を高め、ツールによる事前チェックが可能になります。
この記事では、Pythonにおける静的型付け(型ヒント)の基本的な書き方から、静的解析ツール「mypy」の導入方法、そして導入するメリット・デメリットまで、現在の開発環境に即した実践的なノウハウを解説します。
![]() 執筆者:マヒロ |
|
Pythonにおける「静的型付け」とは?動的型付けとの違い
まず、Pythonが本来持つ「動的型付け」と、今回導入する「静的型付け(型ヒント)」の違いを整理しましょう。
動的型付け(従来のPython)
変数の型は、実行時に値が代入された時点で決まります。
コードはシンプルになりますが、実行するまで型の不一致によるエラー(TypeErrorなど)に気づきにくいというデメリットがあります。
# 動的型付けの例
def add(a, b):
return a + b
print(add(10, 20)) # 30 (OK)
print(add("10", 20)) # エラー! (実行時に初めて気づく)
静的型付け(型ヒントの導入)
Python 3.5から導入された「型ヒント」を使うと、変数や関数の引数・戻り値に「期待する型」を明記できます。
ただし、Pythonの言語仕様自体が変わるわけではなく、実行時には型ヒントは無視されます(強制力はありません)。
その代わり、エディタや解析ツールがこの情報を読み取り、コーディング中に警告を出してくれるようになります。
# 静的型付け(型ヒント)の例
def add(a: int, b: int) -> int:
return a + b
型ヒント(Type Hints)の基本的な書き方
Pythonで型情報を記述するための基本的な構文を見ていきましょう。
Python 3.9以降では、特別なインポートなしでリストや辞書の型指定ができるようになり、非常に書きやすくなっています。
変数と関数の型注釈
# 変数の型注釈
age: int = 25
name: str = "Alice"
is_active: bool = True
# 関数の引数と戻り値の型注釈
# 引数 a, b は int型、戻り値も int型
def multiply(a: int, b: int) -> int:
return a * b
変数名の後ろに : 型名 を記述します。
関数の戻り値は引数リストの後ろに -> 型名 で記述します。
これにより、このコードを読む人(およびツール)は「multiply 関数は整数を受け取り、整数を返す」ことが一目でわかります。
リスト・辞書・タプルの型指定
コレクション(コンテナ)の中身の型も指定できます。
# 整数のリスト
scores: list[int] = [10, 20, 30]
# 文字列のキーと、整数の値を持つ辞書
user_data: dict[str, int] = {"id": 1, "age": 30}
# 文字列と整数を持つタプル
pair: tuple[str, int] = ("apple", 100)
list[int] のように [] を使って内部の型を指定します。
Python 3.8以前では from typing import List のように typing モジュールからのインポートが必要でしたが、現在は組み込み型(list, dict, tuple等)をそのまま使えます。
複数の型を許容する(Union / Optional)
「整数または文字列を受け取りたい」「Noneになる可能性がある」といった柔軟な型指定も可能です。
Python 3.10以降では |(パイプ)演算子を使ってシンプルに記述できます。
# int または str を受け取る (Union型)
def process_id(user_id: int | str) -> None:
print(f"ID is {user_id}")
# str または None (Optional型)
def get_name(name: str | None = None) -> str:
if name is None:
return "Unknown"
return name
int | str は「int型かstr型のどちらか」を意味します。
str | None は、値が存在しない(None)可能性がある場合に使用します。
デフォルト引数に None を設定する場合によく使われるパターンです。
静的型チェックツール「mypy」の導入と使い方
型ヒントを書いただけでは、Pythonはエラーを出してくれません。
型ヒントの効果を最大限に発揮するためには、コードを解析して整合性をチェックするツール 「mypy(マイパイ)」 を導入する必要があります。
mypyのインストール
pipを使って簡単にインストールできます。
pip install mypy
mypyによる型チェックの実行
例えば、以下のような型矛盾のあるコード(type_test.py)があったとします。
# type_test.py
def add(a: int, b: int) -> int:
return a + b
# int型を期待しているのに str型を渡している
result = add(10, "20")
コマンドラインで mypy を実行します。
mypy type_test.py
実行結果
type_test.py:6: error: Argument 2 to "add" has incompatible type "str"; expected "int" [arg-type]
Found 1 error in 1 file (checked 1 source file)
実行前(静的)に「引数2の型が int じゃないよ(str だよ)」とエラーを検出してくれました。
このように、プログラムを動かしてクラッシュさせる前にバグを発見できるのが、mypyを使う最大のメリットです。
Pythonで静的型付けを導入するメリット・デメリット
「手軽さが売りのPythonで、わざわざ型を書く必要があるの?」と疑問に思う方もいるでしょう。
導入判断のために、メリットとデメリットを整理します。
メリット
- バグの早期発見:実行時エラー(Runtime Error)を減らし、開発の手戻りを防げます。
- 可読性の向上:ドキュメントを見なくても、関数の入出力がコードだけで理解できるようになります。
- エディタの補完機能が強力になる:VS Codeなどのエディタが型情報を認識し、メソッドの候補などを正確に提示してくれます(インテリセンスの向上)。
- リファクタリングが安全になる:コードを変更した際の影響範囲が、型エラーとして可視化されやすくなります。
デメリット
- 記述量が増える:シンプルに書けるPythonの良さが少し損なわれ、コードが長くなります。
- 学習コスト:型システムの理解や、ジェネリクスなどの高度な型の扱いに慣れが必要です。
- 実行速度は変わらない:型ヒントは実行時には無視されるため、C++やGoのようにコンパイル最適化による速度向上はありません。
メリットとデメリットを総合的に判断して、導入するかどうかを決めるとよいでしょう。
Pythonのスキルを活かして年収を上げる方法
以上、Pythonの静的型付けについて解説してきました。
なお、Pythonのスキルがある場合には、「転職して年収をアップさせる」「副業で稼ぐ」といった方法を検討するのがおすすめです。
Pythonエンジニアの需要は非常に高いため、転職によって数十万円の年収アップはザラで、100万円以上年収が上がることも珍しくありません。
なお、転職によって年収を上げたい場合は、エンジニア専門の転職エージェントサービスを利用するのが最適です。
併せて、副業案件を獲得できるエージェントにも登録しておくと、空いている時間を活かして稼げるようなPythonの案件を探しやすくなります。
転職エージェントも副業エージェントも、登録・利用は完全無料なので、どんな求人や副業案件があるのか気になる方は、気軽に利用してみるとよいでしょう。



