python / python/mypy

Type narrowing and PEP 634 pattern matching

オープン
#17,622 コメント 0 件 リアクション 3 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

feature
主要言語
Python
スター
20.6k
フォーク
3.3k
PR マージ指標
PR 指標を取得中

説明

Feature

Narrowing a type in a case block that matches the True result of a type-narrowing expression.

Pitch

Hi all- I'd be curious to hear opinions on how realistic the above would be. Here's an example of something that would work if this were implemented:

a: str | None = "hello"

match a is not None:  # or `match isinstance(a, str)`, etc.
    case True:
        print("'a' is a string", a.encode())  # currently: Item "None" of "str | None" has no attribute "encode"
    case False:
        print("'a' is None")

My "pitch" is simply that this feels like it should work (even though it makes sense to me why it doesn't). I think this feeling comes from the fact that, at least on the surface:

if thing:
    blah()
else:
    whatev()

seems morally equivalent to

match thing:
    case True:
        blah()
    case False:
        whatev()

Since I don't have any background with mypy's internals, I'm hoping to hear from the team here how feasible this all sounds.


For context, I ran into this issue when I had a type-narrowing expression embedded in a larger scrutinee (in practice, I can't imagine using match over if if the only thing I were testing was the result of a single type-narrowing expression). Specifically, I was creating a decision table of sorts, and match seemed like a nice way to do that without having to repeat tests:

content: str | bytes
is_text_format: bool

match isinstance(content, str), is_text_format:
    case True, True:
        prepped = content
    case True, False:
        prepped = content.encode("utf-8")  # type narrowing useful here
    case False, True:
        prepped = content.decode("utf-8")  # and here
    case False, False:
        prepped = content

...

I'm sure there are better ways to tackle this bool-centric example, but I think the general question stands on its own outside my original context.


Thank you for your consideration!

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

issue にある 2 つの match の例から始め、要求されている narrowing の動作を現在の mypy の診断と比較してください。issue ではソースファイル、テスト、エントリーポイントが特定されていないため、pattern matching と type narrowing の実装を特定することも作業の一部になります。True と False の分岐で、tuple の scrutinee を含め、match 対象の式が一貫して narrow されれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
python
領域
devtools
issue の種類
機能追加
難易度
5/5
見積もり時間
1週間以上
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
25/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。