You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动