🐍

Pythonの型ヒントと共に進化するコード(#2: イントロダクション)

に公開
本連載の目次


1日目の記事では Recustomer の紹介と、本連載の背景となる「なぜ Recustomer が型を語るのか?」について書きました。

本日 2 日目から本編スタートです。

Python と型

Python は動的型付け言語であり、型は言語の実行システムには組み込まれていません。
しかし Python には 型ヒント という仕組みがあり、これを活用すれば TypeScript や Rust のように型を明示できます。
型ヒントを活用すれば静的解析によって実行前にバグを検出でき、コードの意図を明確に伝えられます。

一方で、型を書かなくてもコードは普通に動きます。
なぜなら言葉の通り Python の型はあくまで型の "ヒント" だからです。

しかし「書かなくても動く」というこの特性が時に落とし穴にもなります。

  • とりあえず動けばいいよね…! と型を省略したり、
  • 型チェッカーの警告を # type: ignore で無理やり黙らせたり、

そうやってせっかくの型安全性を自ら手放してしまうことも少なくないと思います。
正直に言うと、かつての私がそうでした。

心当たり、ありませんか?

もしあなたが、

  • 「とりあえず動く」Python コードは書けるが、数ヶ月後にそのコードを修正するのが怖い
  • # type: ignore を型エラーから目をそらすためのおまじないのように使ってしまうことがある
  • 同僚が書いた型ヒントのない巨大な関数を読解するのに半日を溶かした経験がある
  • Union, Protocol, Generic といった言葉は知っているが、正直なところ自分のコードにどう活かせばいいのか分からない

これらに 1 つでも心当たりがあるなら、この連載はきっとあなたの役に立ちます。

この連載は Python の高度な型ヒントを網羅的に解説するよくあるリファレンス記事ではありません。

ごく普通の「動くけれど脆い」スクリプトが、型ヒントを 1 つずつ取り入れながら「信頼できる堅牢な」コードへと進化していく過程を追ったものです。

この連載で得られること

この連載を見ていただくことで以下の 3 つを身につけることができると考えています。

具体的なリファクタリング手法

dict[str, Any]try-except の多用といったよくあるコードの悪臭を高度な型ヒントを使って段階的に解消していく実践的なプロセスを学べます。

型安全な設計思考

TypedDict, Protocol などを活用し、エラーハンドリングや依存関係の管理を型レベルでどのように設計するかを理解できます。
最終的には Result 型を自作し、例外に頼らない明示的なエラーハンドリングの手法を紹介します。

静的解析のフル活用

型チェッカーを単なるエラー検出ツールとしてではなく、コードの振る舞いを保証し、安全なリファクタリングを支援する頼れる相棒として使いこなす方法がわかります。


そして何より、これらを通して 型のメリットを肌で実感できる ようになることが本連載の最大のゴールです。

読み終える頃には、型ヒントを静的解析のために書かされる面倒なものではなく 自分の開発を助けてくれる強力な武器 として扱えるようになっているはずです。

対象読者

この連載は、以下のような方を対象としています。

  • Python の基本的な文法や関数、クラスの概念を理解している方
  • name: struser_id: int のような基本的な型ヒントを書いた経験がある方
  • 自身の書くコードの品質をもう一段階引き上げたいと考えている意欲的な Python プログラマー
  • チーム開発において、より堅牢でメンテナンス性の高いコードベースを構築したいと考えている方

一方で、プログラミング自体が初めての方や、Python のimportpipといった基本的なエコシステムに不慣れな方には難しく感じられる部分があると思います。

前提

この連載で紹介するコード例は class Foo[T]: ...type Alias[T] = ... といった PEP 695 構文を積極的に活用しています。そのため Python 3.12 以上の環境が必要です。

もし 3.11 以前の環境で同様の型付けを行いたい場合は従来どおりトップレベルで TypeVarTypeAlias を定義するスタイルに書き換えてください。詳しくは公式ドキュメントの TypeVar および TypeAlias の節を参照すると安全に移行できます。

型チェッカーのセットアップ

この連載では「型チェッカー」という言葉が頻繁に登場します。型チェッカーとは、コードを実行することなく型ヒントの整合性を検証するツールです。たとえば「文字列を期待する関数に整数を渡している」といった問題を実行前に検出できます。

Python で最も広く使われている型チェッカーが mypy です。

この連載のコード例を実際に型チェックしながら読み進めると、型ヒントがどのように機能するかをより深く理解できると思います。

インストール

pip install mypy

基本的な使い方

# ファイル単体をチェック
mypy address_fetcher.py

# ディレクトリ全体をチェック
mypy src/

型エラーがあればその箇所と理由が表示されます。エラーがなければ Success: no issues found と出力されます。

推奨設定(pyproject.toml)

プロジェクトで mypy を使う場合は pyproject.toml に設定を記述するのが一般的です。型を積極的に活用するプロジェクト向けの最低限の推奨設定を紹介します。

pyproject.toml
[tool.mypy]
strict = true                # 厳格モードを有効化
show_error_codes = true      # エラーコードを表示(原因特定に便利)
warn_unreachable = true      # 到達不能コードを警告

strict = true を指定すると、以下のような厳格なチェックがまとめて有効になります。

  • 型注釈のない関数定義を禁止
  • Any 型の暗黙的な使用を警告
  • None を返す可能性のある関数の戻り値チェックを厳格化

次回予告

2 日目はここまでです!
明日の 3 日目は、プロローグとして型ヒントを適用する前の「脆いスクリプト」の内容を共有します。
ぜひ明日もお付き合いください 🙏

Discussion