You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mypy能否推断方法返回实例为子类类型?

解决Mypy中父类方法返回子类实例的类型推断问题

原代码如下:

class A:
    
    def __init__(self) -> None:
        pass
    
    def copy(self) -> "A":
        return self.construct_self()
    
    def construct_self(self) -> "A":
        return A()


class B(A):
    
    def __init__(self) -> None:
        super().__init__()
    
    def copy(self) -> "B":
        return super().copy()
    
    def construct_self(self) -> "B":
        return B()

运行Mypy时会触发错误:error: Incompatible return value type (got "A", expected "B") [return-value],但实际运行B().copy()会正确返回B实例。要让Mypy正确推断父类方法返回子类类型,可通过泛型约束实现:

修改后的代码

from typing import TypeVar

# 定义绑定到A的类型变量,限制T为A或其子类
T = TypeVar('T', bound='A')

class A:
    def __init__(self) -> None:
        pass

    # 用self: T标注,让Mypy根据实例实际类型推断返回值类型
    def copy(self: T) -> T:
        return self.construct_self()

    def construct_self(self: T) -> T:
        return self.__class__()  # 用self.__class__创建实例更灵活,也可保留原return A()

class B(A):
    def __init__(self) -> None:
        super().__init__()

    def construct_self(self) -> "B":
        return B()

说明

  1. 泛型约束:通过TypeVar定义与A绑定的类型变量T,在父类方法中用self: T标注self的类型,Mypy会根据当前实例的实际类型(比如B的实例)自动推断T为对应子类类型,因此copy方法的返回类型会被识别为T(即B)。
  2. 无需重写copy方法:修改后子类B不需要重写copy,父类的泛型逻辑已经能让Mypy正确识别B().copy()返回B实例;如果确实需要重写copy,直接标注返回类型为B即可,此时super().copy()的返回类型会被正确推断为B,不会触发类型错误。
  3. 灵活构造实例:将construct_self中的return A()改为return self.__class__(),可以让父类自动创建当前子类的实例,子类只需重写construct_self实现自定义构造逻辑即可。

这样修改后,Mypy能正确识别B().copy()的返回类型为B,调用B的专属方法不会触发类型错误,同时符合你将任务分发到子类实现的场景需求。

内容的提问来源于stack exchange,提问作者GentleMin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 07:02:27