Self类型解决Python 3.11之前无法准确标注返回当前实例类型的问题,例如clone()方法用-> Self可使子类调用时自动推导为子类类型,避免硬编码父类名破坏继承。

Self类型解决什么问题
在Python 3.11之前,给返回当前实例的方法写类型标注很别扭。比如一个clone()方法,你想标注它“返回跟调用者同类型的对象”,但只能写-> MyClass——这会把所有子类的返回类型都硬编码成父类,破坏继承关系。
Self类型怎么用
PEP 673引入了Self,它是typing.Self(3.11+)或from typing_extensions import Self(旧版本兼容)。它不是字符串、不是泛型占位符,而是特指“当前类的运行时类型”:
-
def clone(self) -> Self:—— 子类调用时,类型检查器就知道返回的是子类实例,不是父类 -
def with_name(self, name: str) -> Self:—— 链式调用中每个中间步骤的类型都能被准确推导
注意:Self只能用在实例方法的返回类型里,不能用作参数类型或类属性类型。
不加Self会出什么错
常见误标:def add_item(self, item) -> 'Stack': ...。这种字符串前向引用在子类继承时失效,mypy会报error: Returning incompatible type "ChildStack";而用-> Self后,子类ChildStack().add_item(...)的返回类型自动是ChildStack,无需额外标注。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
立即学习“Python免费学习笔记(深入)”;
另一个坑是误用-> 'Self'(带引号)——这是字符串字面量,不是类型,类型检查器直接忽略。
Self和泛型Self的区别
3.12起支持Self作为泛型参数约束(如class Box[T, Self]),但3.11只支持基础用法。目前绝大多数场景只需-> Self就够了;若涉及复杂继承链或协变返回,才需配合TypeVar(bound=Self),但那是少数情况,容易过度设计。
真正容易被忽略的是:Self依赖类型检查器(如mypy、pyright)支持,CPython解释器本身不校验它——运行时完全无影响,只在静态分析阶段生效。

















