昨日に引き続いて __origin__
という属性について調べていたら、PEP 560 -- Core support for typing module and generic types という PEP にたどり着きました。この PEP は 3.7 から採用されているので、すでに実装が存在して触ることができるやつです。
概要
- 型ヒントが登場したとき、Python 本体に手を入れないように設計していた
- しかし、当時(バージョン 3.6)は 3つの問題があった
-
typing
モジュールのパフォーマンス - メタクラスの競合
-
typing
モジュールで使われている多数のハック
-
アプローチ
-
__class_getitem__
、__mro_entries__
というふたつのスペシャルメソッドを追加する -
__class_getitem__
- クラスオブジェクト向けの
__getitem__
-
Iterable[int]
などの場面で利用される
- クラスオブジェクト向けの
-
__mro_entries__
- クラスではないオブジェクトから派生クラスを作るときに呼び出される
-
__mro_entries__
が返したクラスをもとに派生クラスの MRO を決定する -
typing._GenericAlias
を実現するための仕掛け-
List[int]
の__mro_entries__
はlist
を返すので、実行時はlist
のサブクラスとして振る舞う
-
- クラス定義時の継承クラスは
__orig_base__
に、解決済みの継承クラスは__base__
に保存される
感想
-
typing._GenericAlias
が生まれましたきっかけとなる PEP を読みました - この PEP を読んでから
typing
モジュールを読むとわかりやすいです - PEP をあさり始めた目的であった
__origin__
は、__mro_entries__
を実現するためのプライベートな属性だったというオチでした -
__class_getitem__
もうまく使うとハックしがいがありそうですね