Python 3.11中PEP 612的Y[(q: int), int]是什么?为何注解报错?
关于PEP 612中
Y[(q: int), int]的类型定义及类型错误原因 一、Y[(q: int), int]是什么类型定义?
这是PEP 612引入的参数规格(ParamSpec)的实例化描述,用来精准定义泛型类Y的具体类型:
- 第二个参数
(q: int)是泛型参数P(ParamSpec类型)的具体实例,对应函数a的参数签名——接受一个名为q的int类型参数; - 第一个参数
int是泛型参数U(TypeVar类型)的实例,对应Y类中prop属性的类型。
直白来说,这个描述表示:
- 该
Y实例的prop属性为int类型; - 它的
f属性是一个接受q: int参数、返回str的函数。
二、为什么编写foo: Y[(q: int), int] = ...会触发类型错误?
直接写Y[(q: int), int]违反了Python类型注解的语法规则:
- ParamSpec的使用限制:PEP 612规定,
ParamSpec的实例化只能通过类型推导(比如传入对应签名的函数让类型检查器自动识别),或者使用ParamSpec.args/ParamSpec.kwargs这类语法,不能直接把(q: int)这种函数签名形式作为泛型参数传入。 - 类型表达式合法性要求:Python的泛型参数必须是合法的类型实体,
(q: int)不是可直接引用的类型,类型检查器无法识别这种写法。
如果要显式标注该类型,可通过两种方式实现:
# 方式1:用Callable间接标注 from typing import TypeVar, ParamSpec, Generic, Callable P = ParamSpec("P") U = TypeVar("U") class Y(Generic[U, P]): f: Callable[P, str] prop: U def __init__(self, f: Callable[P, str], prop: U) -> None: self.f = f self.prop = prop def a(q: int) -> str: ... foo: Y[int, Callable[[int], str]] = Y(a, 1)
# 方式2:绑定ParamSpec后标注(需mypy等类型检查器支持) from typing import TypeVar, ParamSpec, Generic, Callable P = ParamSpec("P") U = TypeVar("U") class Y(Generic[U, P]): f: Callable[P, str] prop: U def __init__(self, f: Callable[P, str], prop: U) -> None: self.f = f self.prop = prop def a(q: int) -> str: ... # 绑定对应签名的ParamSpec P_a = ParamSpec("P_a").bind(int) foo: Y[int, P_a] = Y(a, 1)
内容的提问来源于stack exchange,提问作者Mardoxx
相关产品推荐
相关产品推荐

