python / python/typing

Cannot anotate type of generic functions.

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

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

topic: feature
主要言語
Python
スター
1.8k
フォーク
302
平均マージ
23時間
マージ済み PR(30日)
8

説明

The current scoping rules for type variables seems to deny type annotations over generic functions.

The issue

define two functions as follows:

def fx_1(f: Callable[[bool], int]) -> int:
    return f(True)

def fx_2[T](f: Callable[[bool], T]) -> T:
    return f(True)

If a function alias is required, these functions can be assigned to variables. However, if type annotations are used, fx_2 cannot be annotated using compliant type checkers (i.e. pyright).

T = TypeVar("T")
fx_1_alias: Callable[[Callable[[bool], int]], int] = fx_1  # OK!
fx_2_alias: Callable[[Callable[[bool], T]], T] = fx_2  # complains that T has no meaning

Justification

  • All variables should be able to be type annotated, even when those variables are functions or the annotation is not required.
  • def is a syntactic sugar equivalent to a variable assignation over a lambda function. As a result, it should be possible to define generic functions without def statements e.g.
fx_2_alternative: Callable[[Callable[[bool], T]], T] =  lambda f: f(True)
  • Generics are the first ladder of what is called a "dependent type". In the case of functions, this corresponds to a Π type where the input itself is the concrete type that will be replaced on the type var of a generic type. Here type-vars scope is over the function type itself rather than some outer entity (class, function, method).
  • By these definitions of Π type, it cannot exist an unbound type variable when function/callable types are involved, since in python, the type argument is implicit and supplied when referring a TypeVar.
    e.g.
T = TypeVar("T")
fx_2_alias: Callable[[Callable[[bool], T]], T] = fx_2
fx_2_alias_2: Callable[[Callable[[bool], T]], T] = fx_2

Even when using the same type var fx_2_alias and fx_2_alias_2 each var is an independent one.
A more clear syntax (like the introduced on def statements on python312) could be

fx_2_alias: Callable[X][[Callable[[bool], X]], X] = fx_2
fx_2_alias_2: Callable[X][[Callable[[bool], X]], X] = fx_2

This marks explicitly that the scope of the var is over the type itself. However, this issue does not aim to propose a new syntax, but rather aims to adjust the scoping rules of type vars.

Motivation

This issue was derived from a pyright issue where generic functions as class instance variables are denied by the checker because of the same scope issues described before.

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

このリポジトリのコントリビューションガイドは索引されていません

はじめの一歩

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

調査の方向性

ジェネリック関数の例とリンク先の Pyright issue から始め、現在の型変数のスコープ規則と比較します。ジェネリック関数変数およびクラスインスタンス変数のアノテーションについて、typing 仕様で合意された解決策が得られれば完了です。この issue ではリポジトリのファイルやテストは指定しません。

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

評価

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

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

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