添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Python 3.12 版本添加了一个「类型形参列表」的复合语句,用于给函数 (包括 协程), 类 和 类型别名 可能包含类型形参列表,来表明这些参数是泛型。Python 静态类型社区内部一致认为,现在是时候提供一种类似于其他支持泛型类型的现代编程语言的形式语法了。

函数 (包括 协程), 类 和 类型别名 可能包含类型形参列表:

def max[T](args: list[T]) -> T:
async def amax[T](args: list[T]) -> T:
class Bag[T]:
    def __iter__(self) -> Iterator[T]:
    def add(self, arg: T) -> None:
type ListOrSet[T] = list[T] | set[T]

其中,type 语句也是 Python 3.12 增加的,详见:Python type 语句声明类型别名

3.12 新版功能,语法的规则是:

type_params  ::=  "[" type_param ("," type_param)* "]"
type_param   ::=  typevar | typevartuple | paramspec
typevar      ::=  identifier (":" expression)?
typevartuple ::=  "*" identifier
paramspec    ::=  "**" identifier

从语义上讲,这表明函数、类或类型别名是类型变量的泛型。 此信息主要供静态类型检查器使用,并且在运行时,泛型对象的行为与其对应的非泛型对象非常相似。

类型参数是紧接在函数、类或类型别名的名称之后的方括号 ([]) 中声明的。 类型参数可在泛型对象的作用域内访问,但不能在其他地方访问。 因此,在声明 def func[T](): pass 之后,模块作用域中就不能再使用 T 这个名称。 在下文中,将更精确地描述泛型对象的语义。 类型形参的作用域是用一个特殊函数 (从技术上说,是一个 标注作用域) 来模拟的,它封装了泛型对象的创建操作。

泛型函数、类和类型别名都有一个 __type_params__ 属性用于列出它们的类型形参。

类型形参可分为三种:

  • typing.TypeVar,由一个普通名称 (例如 T) 引入。 从语义上讲,这对类型检查器来说代表了一个单独类型。
  • typing.TypeVarTuple,通过在前面添加一个星号的名称来引入 (例如 *Ts)。 从语义上讲,它代表由任意多个类型组成的元组。
  • typing.ParamSpec,通过在前面添加两个星号的名称来引入 (例如 **P)。 从语义上讲,它代表一个可调用对象的形参。
  • typing.TypeVar 声明可以通过在冒号 (: ) 后跟一个表达式来定义 范围 和 约束。 冒号后的单独表达式表示一个范围 (例如 T: int)。 从语义上讲,这意味着 typing.TypeVar 能表示的类型只能是该范围的子类型。 冒号后在圆括号内的表达式元组指定了一组约束 (例如 T: (str, bytes))。 元组中的每个成员都应为一个类型 (同样,在运行时并不强制要求这一点)。 约束的类型变量只能使用约束列表内的类型中选择一种。

    对于使用类型形参列表语法声明的 typing.TypeVar,范围和约束在创建泛型对象时并不会被求值,只有在通过属性 __bound____constraints__ 显式地访问它时才会被求值。 要做到这一点,需要在单独的 标注作用域 中对范围和约束进行求值。

    typing.TypeVarTupletyping.ParamSpec 不能拥有范围或约束。

    下面的例子显示了所有被允许的类型形参声明:

    def overly_generic[
       SimpleTypeVar,
       TypeVarWithBound: int,
       TypeVarWithConstraints: (str, bytes),
       *SimpleTypeVarTuple,
       **SimpleParamSpec,
       a: SimpleTypeVar,
       b: TypeVarWithBound,
       c: Callable[SimpleParamSpec, TypeVarWithConstraints],
       *d: SimpleTypeVarTuple,
    ): ...
    
  • https://peps.python.org/pep-0695/
  • https://docs.python.org/zh-cn/3.12/reference/compound_stmts.html#type-parameter-lists
  • https://docs.python.org/zh-cn/3.12/library/typing.html#generics
  •