泛型类中使用PEP 673 Self[DataOut]报错,该用法是否支持?
问题解答
当前PEP 673定义的Self类型不支持Self[DataOut]这种带类型参数的写法,这也是你在Pylance/Pyright中报错的原因。
为什么不行?
Self的设计初衷是指代当前实例的具体类型——包括它已经绑定的泛型参数。比如你有一个Msg[int]的实例,Self就等价于Msg[int],它是一个具体的类型,而非可以重新指定泛型参数的类模板。所以给Self添加类型参数本身就不符合它的语义,类型检查器自然会报错。
PEP 673文档中提到的“Self也可用于泛型类方法”,指的是在方法中返回与当前实例同泛型参数的实例场景,比如:
def clone(self) -> Self: return Msg(source=self.source, data=self.data)
这种场景下Self可以正确指代当前实例的泛型类型,而不是用来生成一个新泛型参数的实例。
替代方案
如果你想避免使用字符串引用,有两种可行的方式:
1. 启用延迟注解(Python 3.10+)
导入from __future__ import annotations后,类型注解会延迟解析,直接写Msg[DataOut]即可,不需要加引号:
from __future__ import annotations from dataclasses import dataclass from typing import Generic, TypeVar DataIn = TypeVar('DataIn') DataOut = TypeVar('DataOut') @dataclass class Msg(Generic[DataIn]): source: str data: DataIn def next(self, data: DataOut) -> Msg[DataOut]: """创建一个相同source但不同data的新消息""" return Msg(source=self.source, data=data)
2. 使用绑定的TypeVar(兼容更早版本)
定义一个绑定到Msg的TypeVar,用来表示泛型的Msg类型:
from dataclasses import dataclass from typing import Generic, TypeVar DataIn = TypeVar('DataIn') DataOut = TypeVar('DataOut') MsgType = TypeVar('MsgType', bound='Msg') @dataclass class Msg(Generic[DataIn]): source: str data: DataIn def next(self, data: DataOut) -> Msg[DataOut]: return Msg(source=self.source, data=data)
总结
返回不同泛型参数的同类实例时,Self类型无法满足需求,推荐直接使用类名加类型参数的写法(启用延迟注解后无需字符串)。
内容的提问来源于stack exchange,提问作者davetapley
相关产品推荐
相关产品推荐

