Python 3.12 引入 PEP 695 新语法,支持 class Stack[T]: 等简洁泛型定义,类型参数可带约束(T: int)和默认值(=int),__parameters__ 成为类直接属性,旧版兼容需回退到 Generic 写法。

Python 3.12 的 TypeVar 和 Generic 写法变了
Python 3.12 正式支持 PEP 695 —— 类型参数语法(Type Parameter Syntax),它让泛型类定义更简洁、更接近其他语言的直觉写法。以前必须写 class Stack(Generic[T]):,现在可以直接用 class Stack[T]:。这不是语法糖,是语义等价的新语法,且优先级更高。
注意:旧写法仍可用,但新写法更推荐,尤其在定义多个类型参数或带约束时更清晰。
-
T = TypeVar("T")依然要 import,但不再需要显式继承Generic[T] - 类型参数直接写在类名后方方括号里,如
class Box[T]:,不加括号会报SyntaxError: expected ':' - 类型参数可带约束、协变/逆变标记,例如
class Mapper[K: str, V] (covariant=True):—— 注意K: str表示K必须是str或其子类型(运行时不检查,仅静态类型检查器识别)
带约束和默认值的类型参数怎么写
PEP 695 允许在类型参数中直接声明约束(bound)和默认值(default),这比过去用 TypeVar("T", bound=...) or TypeVar("T", default=...) 更紧凑。
比如想定义一个只接受数字的容器,并默认为 int:
class NumberList[T: (int, float) = int]:
def __init__(self, items: list[T] = None) -> None:
self.items = items or []
这里 T: (int, float) 是 bound 元组(表示 T 必须是 int 或 float 的子类型),= int 是默认类型参数。静态类型检查器(如 mypy 1.10+、pyright)能识别该默认值,调用 NumberList() 时自动推导为 NumberList[int]。
- 约束必须是类型表达式,不能是字符串或变量名;
T: "int | float"会报错 - 默认值只能是类型字面量(如
int、str、list[str]),不能是复杂表达式 - 如果同时用了 bound 和 default,default 必须满足 bound(如
T: int = str不合法)
嵌套泛型类和方法中的类型参数冲突
当类本身有类型参数,又在内部定义泛型方法时,容易误复用同名类型变量,导致意外覆盖或绑定错误。
Python 环境工具专业版功能概述Python 环境工具专业版是一项面向实际任务的技能。它将相关步骤、工具调用和结果整理方式集中到统一流程中,帮助使用者更快完成目标并减少重复操作。核心要点使用时应结合输入条件选择合适的执行方式,核对必要参数、依赖环境与输出内容,并按原始要求处理异常情况。该技能适合需要稳定复用相关能力的场景,可作为自动化工作流的一部分,也便于后续检查、调整和扩展。执行完成后建议检查结果是否符合预期,并保留必要记录。使用与执行同时注意输入完整性、执行条件和输出可用性。从功能定位来看,该技能
错误示例:class Processor[T]: def map[U](self, f: Callable[[T], U]) -> list[U]: ... —— 这没问题;但若写成 def map[T](self, ...),这个 T 就会遮蔽外层类的 T,不再是同一个类型变量。
- 类级类型参数作用域仅限于类体,方法内重新声明同名参数会创建新绑定
- 想在方法中引用类的
T,就不要在方法签名里再声明T;需要独立参数时,务必换名(如U,V) - 类方法(
@classmethod)中若需泛型,也得显式声明自己的类型参数,不能依赖类的[T]
运行时反射和 __parameters__ 的变化
新语法下,__parameters__ 仍存在,但获取方式略有不同:它现在是类对象的直接属性,而非从 Generic 继承而来。这意味着你不能再靠 isinstance(cls, Generic) 判断是否泛型类(该检查在 3.12 中失效)。
正确做法是检查 cls.__parameters__ 是否非空且为 tuple:
def is_generic_class(cls) -> bool:
return hasattr(cls, "__parameters__") and bool(cls.__parameters__)
-
get_args(cls)和get_origin(cls)(来自typing)对新语法完全兼容,无需改动 - 动态构造泛型类(如
SomeClass[int])的行为没变,但若手动操作__parameters__,要注意它现在是只读 tuple,不可修改 - 第三方库(如 pydantic v2.8+、fastapi 0.115+)已适配,但旧版 ORM 或序列化工具可能尚未识别新语法,遇到
TypeError: 'X' is not a generic class时需确认其 typing 支持版本
真正麻烦的是跨版本兼容:如果你的包要支持 Python 3.11 及更早版本,就不能用 class C[T]: 这种写法——它在 3.11 下直接 SyntaxError。此时必须继续用传统 Generic 写法,或通过字符串注解 + typing_extensions 回退。别指望 type checker 自动降级处理。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










