1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonのtyping.ProtocolとABCの違いと実務的な考察

Posted at

Pythonのtyping.Protocol徹底解説と実務的な見解

1. イントロ

Pythonで「インターフェースを表現したい」と思ったことはありませんか?
抽象基底クラス(ABC)は少し重く感じるし、柔軟性に欠ける…。
そんなときに登場するのが typing.Protocol です。

この記事では、

  • Protocolの仕組み
  • 使える場面と便利さ
  • そして実務的には「推奨しない」という著者の立場

をまとめます。


2. 背景

PythonはDuck Typingの文化を持っています。
「アヒルのように歩いて、ガーガー鳴くなら、それはアヒル」。

型ヒントやProtocolは、このDuck Typingを**静的型チェッカー(mypy, pyrightなど)**の世界に持ち込む仕組みです。
注意点は、実行時には何もチェックされないことです。


3. Protocolの最小例

まずは簡単な例を見てみましょう。

from typing import Protocol

class Greeter(Protocol):
    def greet(self) -> str: ...

class Person:
    def greet(self) -> str:
        return "Hello!"

def say_hello(g: Greeter) -> None:
    print(g.greet())

say_hello(Person())  # ✅ OK

PersonGreeterを継承していません。
でもgreet()メソッドを持っているので、Protocolを満たすとみなされます。

これが「構造的部分型(structural subtyping)」です。


4. ABCとの比較

比較項目 Protocol ABC
継承必須 ❌ 不要(構造さえ揃えばOK) ✅ 必要
実行時チェック ❌ なし isinstanceで可能
柔軟性 高い 低い
適用場面 外部ライブラリ/後付けインターフェース 厳格な契約

Protocol = 構造的部分型
ABC = 名目的部分型


5. 実践ユースケース

サービス層 / リポジトリ層

class Storage(Protocol):
    def save(self, key: str, data: bytes) -> None: ...
    def load(self, key: str) -> bytes: ...

class S3Storage:
    def save(self, key: str, data: bytes) -> None: ...
    def load(self, key: str) -> bytes: ...

class LocalStorage:
    def save(self, key: str, data: bytes) -> None: ...
    def load(self, key: str) -> bytes: ...

呼び出し側はStorageを受け取るだけで、S3とローカルを差し替え可能。


テストダブル(モック/スタブ)

class FakeStorage:
    def save(self, key: str, data: bytes) -> None: ...
    def load(self, key: str) -> bytes: ...

Storageを満たすので、テストで安全に利用できる。


外部ライブラリとの相性

class CsvExportable(Protocol):
    def to_csv(self, path: str) -> None: ...

def export(obj: CsvExportable, path: str) -> None:
    obj.to_csv(path)

pandas.DataFrameのようにto_csvを持つクラスなら、そのまま利用できる。


6. ベストプラクティス

  • 自分で管理するクラス → 明示的にProtocolを継承して「このクラスはこれを実装している」と示す
  • 外部ライブラリや既存コード → 継承なしでProtocolを当てはめると便利
  • 必ずCIに型チェッカーを導入すること(mypy/pyright)

7. 自身の見解(推奨しない理由)

便利そうに見えるProtocolですが、実務での利用には慎重さが必要です。

  • 実行時には何も保証されない
    • 型が間違っていても、mypyを通さなければ普通に動いてしまう
  • 意図がコードから読み取りづらい
    • 継承不要なので「なぜこのクラスがProtocol適合しているのか」が一目で分からない
  • チーム開発では混乱を招く可能性
    • 新規参加者がコードを見ても「どのインターフェースを満たす想定か」理解しづらい
  • 結局テストに頼るしかない
    • 型だけで安全性は担保できない

👉 よって、著者は「基本的には推奨しない」立場です。
ただし、以下のケースでは有効だと考えます。

  • テスト用のモック/スタブの型保証
  • 外部ライブラリを柔軟にインターフェース化したいとき

8. まとめ

  • Protocolは「Pythonにおける型安全なインターフェース」
  • 便利だが諸刃の剣
  • 実務で使うなら 小さく・限定的に・型チェックとテスト込みで
  • 保守性を重視するなら、ABCや明示的な継承の方が無難

💡 練習課題:
あなたのプロジェクトで「Protocolで表せるインターフェース」はありますか?
ぜひ考えてみてください。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?