Python 3.12 引入泛型声明语法革新:类、函数、类型别名中直接使用[T]、[K,V],无需Generic或TypeVar;class Box[T]:、def func[T]():、type ListOrSet[T] = ... 均原生支持,仅类型检查阶段生效。

list[str] 和 dict[str, int] 这类写法不是 3.12 引入的——它们从 Python 3.9 就已可用。真正由 3.12 带来的,是泛型「声明」层面的语法革新:类、函数、类型别名中直接使用 [T]、[K, V],不再需要 Generic 或 TypeVar。
class Box[T]: 不再需要继承 Generic[T]
旧写法必须显式导入并继承:from typing import Generic, TypeVar + T = TypeVar('T') + class Box(Generic[T]):。3.12 中 class Box[T]: 即可,解释器自动识别 T 为类型变量。
-
T是隐式声明的,作用域限于该类内部;多个参数如[K, V]也直接支持 - 不兼容旧版 Python(3.11 及之前会报
SyntaxError: invalid syntax) - 类体里仍需用
T做标注(如def __init__(self, item: T)),不能写成item: "T" - 运行时行为不变:
Box[int]()和Box[str]()仍是同一个类对象,仅类型检查器参与泛型推导
def first[T](items: list[T]) -> T: 不再需要单独定义 TypeVar
以前写泛型函数得先定义 T = TypeVar('T'),再套进签名里;现在 def first[T](...) 一行搞定,T 在函数签名和函数体内都可见。
- 函数内不能重复声明同名类型变量(
def func[T, T](...)报错) - 支持带约束的声明,如
def copy[T: (int, str)](x: T) -> T:,但注意括号里是元组字面量,不是 Union - 若函数返回值用到类型变量,必须出现在参数或返回注解中,否则 mypy 会警告“unused type variable”
type ListOrSet[T] = list[T] | set[T]: type 语句替代 TypeAlias
旧方式靠赋值 + TypeAlias 注解(如 ListOrSet: TypeAlias = list[T] | set[T]),3.12 用 type 关键字更清晰,且原生支持泛型参数。
立即学习“Python免费学习笔记(深入)”;
-
type是软关键字:只在类型别名上下文生效,不影响已有变量名(比如你还能定义type = "string") - 不能在运行时求值:右侧不能含动态表达式,如
type Bad[T] = list[T] if True else dict[T, T]语法错误 - 与泛型类/函数不同,
type声明本身不产生新类型对象,只是别名,isinstance(x, ListOrSet)无效
真正容易被忽略的是:这些新语法只影响类型检查阶段,运行时不生成额外对象,也不改变 <strong>annotations</strong> 结构。如果你依赖反射(比如框架扫描类型注解做序列化),得确认工具是否已适配 PEP 695 解析逻辑——很多老版本 mypy 或 pydantic v1 就不认 class Box[T]: 这种写法。


















