Python 3.15ではより正確な型チェックが可能に(なる予定) PEP 800で導入される非交和基底とは?Deep Insider Brief ― 技術の“今”にひと言コメント

Python 3.15をターゲットとしたPEP 800が承認された。これが提案する「あるクラスが非交和基底であること」と、それを示す@disjoint_baseデコレーターについて紹介する。

» 2026年04月24日 05時00分 公開
[かわさきしんじDeep Insider編集部]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「Deep Insider Brief ― 技術の“今”にひと言コメント」のインデックス

連載目次

 2026年4月15日、Python 3.15向けのPEP 800「Disjoint bases in the type system」(型システムにおける非交和基底)が承認された。StatusがAcceptedになったことから、Python 3.15での非交和基底とそれを示す@disjoint_baseデコレーターの導入が見込まれる。以下ではこれについて簡単に説明しよう。

PEP 800の概要ページ(peps.python.org) PEP 800の概要ページ(peps.python.org)
PEP 800 - Disjoint bases in the type system」をキャプチャーして引用


HPかわさき

 どうも。HPかわさきです。

 「最近、趣味に走ってPythonネタばっかりやってるだろ」と思っている方もいらっしゃるかもしれません。一応、いろいろとニュースっぽい記事のネタは探しているのですが、筆者の心に刺さるのがPythonネタになっちゃっているんですよね。Pythonばっかり取り上げるのはよろしくないなぁ(笑)。でも、好きなんだよなぁ。


あるコードの到達可能性をチェックするには

 PEP 800について話す前に、以下のコードを見てほしい。

def f(x: int):
    if isinstance(x, str):
        print('x is int and also string')

到達不可能なコードの例

 このコードはint型の値を受け取り、それをif文でstr型のインスタンスかどうかチェックしている。isinstance関数の戻り値がTrueとなることはないので、print関数呼び出しには到達できない。以下の画像は、Visual Studio CodeにMypy Type Checker拡張機能をインストールして、「--warn-unreachable」を有効にして、上記コードを開いたところだ。

到達不可能なコードの例 到達不可能なコードの例

 先ほどの到達か不可能なコードに関する振る舞いは型チェッカーによって異なることにも注意が必要だ。例えば、上記のコードでMypy Type Checker拡張機能を無効にしてみると、以下のようにPylanceはこれを到達不可能とは見なしていないことが分かる。

Pylanceは先ほどのコードは到達不可能とは見なしていないようだ Pylanceは先ほどのコードは到達不可能とは見なしていないようだ

 f関数は全てのコードがハッキリと表示されているが、g関数は2つ目のreturn文がグレーアウトされている。これはPylanceがこのreturn文を到達不可能だと見なしているからだ。

 このように型チェッカーによって、到達不可能なコードの判定が異なるのは問題がある。このような状況を解決するために提案されたのがPEP 800であり、非交和基底という概念だ。

PEP 800で導入される非交和基底とは

 先ほどのコードをもう一度見てみよう。

def f(x: int):
    if isinstance(x, str):
        print('x is int and also string')

到達不可能なコードの例

 if文にあるprint関数が実行されるには「xはint型であり、str型でもある」ことが必要だ。だが、実際にはそうしたクラスは存在できない。

class C(int, str):
    pass

c = C()

intとstrを多重継承するクラスは定義できない

 このコードを実行すると、次の画像のようにエラーとなる。

intとstrを継承するクラスは定義できない intとstrを継承するクラスは定義できない

 Mypyでは、ヒューリスティックな方法を使うことで、こうしたエラーを検出できているが、Pythonの型システムで「このクラスとこのクラスを同時に継承するクラスは存在できない」を表現することができるようにするために「非交和基底」という概念が導入された。

 集合論に近い表現をすると「非交和基底」とは「あるクラスのインスタンスの全集合が、別のクラスのインスタンスの全集合と交わることがない」のようになるだろう。intとstrを例に取れば、それらのインスタンスは整数値の集合と文字列の集合であり、交わることがないということだ。

 PEP 800によれば、あるクラスが非交和基底であることは、@disjoint_baseデコレーターで示す。そして、このデコレーターが付いた2つのクラスを同時に継承しようとすると、型チェッカーがエラーとして検出できるようになるというわけだ。


HPかわさき

 PEP 800では「Pythonプログラムを解析するときには、型チェッカーは2つのクラスが共通の子クラスを持てるかどうかをチェックできる必要がある」とあります。チェックに必要なマーカーが@disjoint_baseデコレーターだと考えるのがカンタンかもしれませんね。


 例えばint型とstr型の双方が@disjoint_baseデコレーターで修飾されていれば、先ほどのコードのif文を型チェッカーが見たときに「これは到達不可能である」と判定できるようになる(既に述べたが、if文の条件が真になるには「xはintでもあり、strでもある」必要があるからだ)。


HPかわさき

 Mypyは恐らく「xはintでもあり、strでもある」ことはないと考えて、エラーを発見していますが、その論理的な根拠が非交和基底にあると筆者は理解しています。少なくともピュアなPython 3.14のコードでは、エラーの判定に非交和基底をベースにした何かの技術が使われているわけではありません。

 なお、Mypy 1.18.1以降とtyping-extension 4.15.0の組み合わせでは、@disjoint_baseデコレーターによる非交和基底のマーキングや、それに基づいたエラーの検出が可能なようです。いち早く、この機能を使って見たいという方はぜひ。


 @disjoint_baseデコレーターの使い方のイメージは次のようになる。

@disjoint_base  # このクラスは非交和基底
class C0:
    pass

@disjoint_base  # このクラスも非交和基底
class C1:
    pass

class D(C0, C1):  # 2つの非交和基底クラスを多重継承はできない
    pass

非交和基底なクラスを複数

 ただし、このデコレーターは一般のユーザーが直接使う場面はほぼなく、int、str、floatなどの組み込み型や標準ライブラリのスタブファイル(型情報を記述した定義ファイル)に付与されることを主な用途として考えられている。


HPかわさき

 非交和基底がちゃんと機能するロジックを説明しだすと、いろいろとタイヘンなので、今回は細かなことは省略しています(@disjoint_baseデコレーターを付加したクラスとその派生クラスなら多重継承が可能とか。object型も非交和基底となるとか。多重継承するときにどのようにして、複数の非交和基底なクラスを継承しようとしているかを判定しているかとか……。タイヘンそうですよね)。


「Deep Insider Brief ― 技術の“今”にひと言コメント」のインデックス

Deep Insider Brief ― 技術の“今”にひと言コメント

Copyright© Digital Advantage Corp. All Rights Reserved.

アイティメディアからのお知らせ

スポンサーからのお知らせPR

注目のテーマ

その「AIコーディング」は本当に必要か?
Microsoft & Windows最前線2026
4AI by @IT - AIを作り、動かし、守り、生かす
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。