.. _`special-types`: アノテーションにおける特別な型 ========================================================================================== .. _`any`: ``Any`` ------------------------------------------------------------------------------------------ ``Any`` は未知の静的型を表します。 すべての型は ``Any`` に :term:`assignable` であり、``Any`` はすべての型に割り当て可能です。 ``Any`` についての詳細な議論は :ref:`type-system-concepts` を参照してください。 アノテーションのない関数パラメータは ``Any`` でアノテートされていると見なされます。 ジェネリック型が型パラメータを指定せずに使用される場合、それらは ``Any`` と見なされます:: from collections.abc import Mapping def use_map(m: Mapping) -> None: # Mapping[Any, Any] と同じ ... このルールは ``tuple`` にも適用され、アノテーションコンテキストでは ``tuple[Any, ...]`` と同等です。 同様に、アノテーション内の裸の ``Callable`` は ``Callable[..., Any]`` と同等です:: from collections.abc import Callable def check_args(args: tuple) -> bool: ... check_args(()) # OK check_args((42, 'abc')) # これも OK check_args(3.14) # 型チェッカーによってエラーとしてフラグが立てられる # 任意のコール可能オブジェクトのリストはこの関数によって受け入れられます def apply_callbacks(cbs: list[Callable]) -> None: ... ``Any`` は基底クラスとしても使用できます。 これは、どこでもダックタイプできるクラスや非常に動的なクラスで型チェッカーのエラーを回避するのに役立ちます。 .. _`none`: ``None`` ------------------------------------------------------------------------------------------ 型ヒントで使用される場合、式 ``None`` は ``type(None)`` と同等と見なされます。 .. _`noreturn`: ``NoReturn`` ------------------------------------------------------------------------------------------ ``typing`` モジュールは、通常は決して戻らない関数をアノテートするための :term:`special form` ``NoReturn`` を提供します。 たとえば、無条件に例外を発生させる関数:: from typing import NoReturn def stop() -> NoReturn: raise RuntimeError('no way') ``NoReturn`` アノテーションは ``sys.exit`` などの関数に使用されます。 静的型チェッカーは、``NoReturn`` を返すとアノテートされた関数が本当に戻らないことを確認します。暗黙的または明示的に:: import sys from typing import NoReturn def f(x: int) -> NoReturn: # エラー、f(0) は暗黙的に None を返す if x != 0: sys.exit(1) チェッカーは、そのような関数への呼び出し後のコードが到達不能であることを認識し、それに応じて動作します:: # 最初の例から続ける def g(x: int) -> int: if x > 0: return x stop() return 'whatever works' # 一部のチェッカーは到達不能なブロック内のエラーを無視するため、エラーが報告されない場合があります .. _`never`: ``Never`` ------------------------------------------------------------------------------------------ Python 3.11 以降、``typing`` モジュールには :term:`special form` ``Never`` が含まれています。 これは、空の Python オブジェクトのセットを表すボトム型を表します。 ``Never`` 型は上記の ``NoReturn`` と同等です。 ``NoReturn`` 型は関数の戻り値のアノテーションに慣習的に使用され、``Never`` は他の場所で使用されることが一般的ですが、2 つの型は完全に交換可能です。 .. _`numeric-promotions`: ``float`` および ``complex`` の特別なケース ------------------------------------------------------------------------------------------ Python の数値型 ``complex``、``float`` および ``int`` は互いのサブタイプではありませんが、一般的なユースケースをサポートするために、型システムには簡単なショートカットが含まれています。 引数が ``float`` 型としてアノテートされている場合、``int`` 型の引数は許容されます。同様に、引数が ``complex`` 型としてアノテートされている場合、``float`` または ``int`` 型の引数は許容されます。 .. _`type-brackets`: ``type[]`` ------------------------------------------------------------------------------------------ クラスオブジェクト、特に特定のクラスを継承するクラスオブジェクトについて話したい場合があります。 これは ``type[C]`` として表記できます。 ``C`` はクラスです。 明確にするために: ``C`` (アノテーションで使用される場合) はクラス ``C`` のインスタンスを指しますが、``type[C]`` は ``C`` の *サブクラス* を指します。 (これは ``object`` と ``type`` の間の区別と似ています。) たとえば、次のクラスがあるとします:: class User: ... # User クラスの抽象基底 class BasicUser(User): ... class ProUser(User): ... class TeamUser(User): ... そして、クラスオブジェクトを渡すとこれらのクラスのインスタンスを作成する関数があるとします:: def new_user(user_class): user = user_class() # (ここでユーザーオブジェクトをデータベースに書き込むことができます) return user ``type[]`` をサブスクリプトしない場合、``new_user()`` をアノテートするためにできる最善の方法は次のとおりです:: def new_user(user_class: type) -> User: ... ただし、``type[]`` と上限を持つ型変数を使用すると、はるかに優れた方法が可能です:: U = TypeVar('U', bound=User) def new_user(user_class: type[U]) -> U: ... これで、特定の ``User`` サブクラスを使用して ``new_user()`` を呼び出すと、型チェッカーは結果の正しい型を推測します:: joe = new_user(BasicUser) # 推測された型は BasicUser です ``type[C]`` に対応する値は、``C`` のサブタイプである実際のクラスオブジェクトでなければなりません。 つまり、上記の例では、``new_user(BasicUser | ProUser)`` を呼び出すと、型チェッカーによって拒否されます (ランタイムで失敗することに加えて、結合をインスタンス化できないため)。 ``type[]`` のパラメータとしてクラスの結合を使用することは合法です。次のように:: def new_non_team_user(user_class: type[BasicUser | ProUser]): user = new_user(user_class) ... ``type[]`` は結合に分配されます: ``type[A | B]`` は ``type[A] | type[B]`` と :term:`equivalent` です。 ただし、ランタイムで渡される実際の引数は具体的なクラスオブジェクトでなければなりません。上記の例では:: new_non_team_user(ProUser) # OK new_non_team_user(TeamUser) # 型チェッカーによって許可されていません ``type[Any]`` もサポートされています (その意味については以下を参照してください)。 ``T`` が型変数である場合、クラスメソッドの最初の引数をアノテートする場合に ``type[T]`` が許可されます (関連セクションを参照してください)。 ``tuple`` や ``Callable`` などの他の特別な構成要素は、``type`` の引数として許可されていません。 この機能にはいくつかの懸念があります。たとえば、``new_user()`` が ``user_class()`` を呼び出すと、``User`` のすべてのサブクラスがそのコンストラクタシグネチャでこれをサポートする必要があることを意味します。 ただし、これは ``type[]`` に固有のものではありません。クラスメソッドにも同様の懸念があります。 型チェッカーはそのような仮定の違反をフラグ付けする必要がありますが、デフォルトでは、指定された基底クラス (上記の例では ``User``) のコンストラクタシグネチャに一致するコンストラクタ呼び出しが許可されるべきです。 複雑または拡張可能なクラス階層を含むプログラムは、ファクトリクラスメソッドを使用してこれを処理することもできます。 ``type`` がパラメータ化される場合、正確に 1 つのパラメータが必要です。 かっこなしのプレーンな ``type`` は、Python のメタクラス階層のルートであり、``type[Any]`` と同等です。 ``type[Any]`` (または ``type``) の動作に関しては、この型の変数の属性にアクセスすると、``type`` によって定義された属性とメソッド (たとえば、``__repr__()`` および ``__mro__``) のみが提供されます。 そのような変数は任意の引数で呼び出すことができ、戻り値の型は ``Any`` です。 ``type`` はそのパラメータに対して共変です。なぜなら、``type[Derived]`` は ``type[Base]`` のサブタイプだからです:: def new_pro_user(pro_user_class: type[ProUser]): user = new_user(pro_user_class) # OK ...