Python泛型新语法(PEP 695)解析及等效性确认问询
Python泛型新语法(PEP 695)解析及等效性确认问询
最近我研究了Python 3.12引入的PEP 695新泛型语法,发现它其实只是语法糖,来跟大家拆解下细节:
首先看3.12+支持的新泛型写法:
class Bag[T]: pass
它等价于类似下面这种更底层的实现逻辑(编译器会自动做转换):
def TYPE_PARAMS_OF_Bag(): T = typing.TypeVar("T") class Bag(typing.Generic[T]): __type_params__ = (T,) ... return Bag Bag = TYPE_PARAMS_OF_Bag()
简单说,Python编译器会把新泛型语法转成类似上面的包裹形式,本质上创建泛型的核心逻辑还是基于class Bag(typing.Generic[T]),新写法只是帮我们省掉了手动定义类型变量、继承Generic的繁琐步骤。
我们可以通过对比不同Python版本的代码运行结果来验证这点:
3.12/3.13版本的写法:
class MyClass[T]: pass print(MyClass.__mro__)3.11及更早版本的写法:
import typing as t T = t.TypeVar('T') class MyClass2(t.Generic[T]): pass print(MyClass2.__mro__)
两段代码的运行结果完全一致:
(<class '__main__.MyClass'>, <class 'typing.Generic'>, <class 'object'>) (<class '__main__.MyClass2'>, <class 'typing.Generic'>, <class 'object'>)
PEP 695推出这个新语法的初衷,是为了解决之前项目里到处定义全局T=typing.TypeVar('T')类型变量带来的混乱问题——新语法会把类型变量封装在专属的作用域里,还会自动处理注解相关的结构,让泛型定义更简洁。
那回到核心问题:class MyClass[T]和class MyClass(t.Generic[T])完全等价吗?
答案是从运行时行为和泛型类的本质来看,二者是等效的。新语法只是语法糖,最终都会被编译器转成基于typing.Generic的实现;但新写法帮我们简化了类型变量的定义和作用域管理,是对旧写法的友好升级。
备注:内容来源于stack exchange,提问作者ywp




