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

子类用父类属性子类型重写时如何解决mypy类型不兼容问题

解决Mypy中列表子类类型兼容性问题

问题代码

class B:
    pass


class InheritsB1(B):
    pass


class InheritsB2(B):
    pass


class A:
    prop: list[B]


class InheritsA1(A):
    prop: list[InheritsB1]


class InheritsA2(A):
    prop: list[InheritsB2]

问题描述

运行上述代码时,mypy会抛出错误:

Incompatible types in assignment (expression has type "List[InheritsB2]", base class "A" defined the type as "List[B]")

虽然InheritsB1、InheritsB2都是B的子类,但Python的list是不变类型——list[InheritsB1]并不被视为list[B]的子类,因此mypy会判定类型不兼容。我们需要让父类A的prop支持“B或其任意单一子类的列表”,且列表内不会混合不同子类实例。

解决方案

使用泛型(Generic)+ 绑定类型变量(Bound TypeVar)来实现类型兼容,具体修改如下:

from typing import TypeVar, Generic

# 定义一个类型变量,只能绑定B或其子类
T = TypeVar('T', bound=B)

class B:
    pass


class InheritsB1(B):
    pass


class InheritsB2(B):
    pass


# 让A继承Generic[T],成为泛型类
class A(Generic[T]):
    prop: list[T]


# 子类继承时指定具体的类型参数
class InheritsA1(A[InheritsB1]):
    pass


class InheritsA2(A[InheritsB2]):
    pass

方案说明

  • 通过TypeVar('T', bound=B)限制类型变量T只能是B或其子类,保证类型安全。
  • 父类A声明为泛型类后,prop的类型list[T]会随子类指定的T而变化:InheritsA1的prop自动变为list[InheritsB1],InheritsA2的prop自动变为list[InheritsB2]。
  • 这种方式既满足了“列表仅包含单一子类实例”的需求,又让mypy能够正确识别类型兼容性,同时新增B的子类时无需修改父类代码,扩展性更强。

替代方案(不推荐)

如果不想使用泛型,有两种妥协方式,但都存在明显缺陷:

  • 在子类的prop声明后添加# type: ignore忽略mypy错误,但会牺牲类型检查的严谨性。
  • 将父类A的prop声明为list[B | InheritsB1 | InheritsB2],但新增B的子类时需要手动更新联合类型,灵活性极差。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 04:26:55