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

Mypy类型检查问题:定义适配TypedDict子类的抽象类方法

解决TypedDict与抽象类方法参数的类型兼容问题

错误原因

mypy报错是因为方法参数遵循逆变规则:子类重写方法时,参数类型必须是父类参数类型的超类型(或相同),确保任何能传给父类方法的参数,都能正常传给子类方法。你的代码里,DictWithAandB和DictWithAandC是DictWithA的子类(更窄的类型),子类foo方法仅接受更窄的类型,违反了里氏替换原则,因此mypy抛出类型不兼容的错误。

解决方案:用泛型TypeVar绑定约束

通过定义绑定到DictWithA的TypeVar,将抽象类改为泛型类,让每个子类指定自己对应的TypedDict类型,既满足抽象类对“包含键'a'的字典”的约束,又能让子类方法接受特定的扩展字典类型。

修正后的代码:

from abc import ABC
from typing import TypedDict, TypeVar, Generic

# 定义绑定到DictWithA的TypeVar,限制T只能是DictWithA或其子类
T = TypeVar('T', bound='DictWithA')

class DictWithA(TypedDict):
    a: bool

class DictWithAandB(DictWithA):
    b: int

class DictWithAandC(DictWithA):
    c: int

# 将抽象类声明为泛型类,使用T作为foo方法的参数类型
class AbstractClass(ABC, Generic[T]):
    def foo(self, bar: T) -> int:
        raise NotImplementedError()

class ConcreteClassB(AbstractClass[DictWithAandB]):
    def foo(self, bar: DictWithAandB) -> int:
        return bar["b"] if bar["a"] else 0

class ConcreteClassC(AbstractClass[DictWithAandC]):
    def foo(self, bar: DictWithAandC) -> int:
        return bar["c"] if bar["a"] else 2

代码说明

  • T = TypeVar('T', bound='DictWithA'):限定T的取值范围为DictWithA或其子类,保证抽象类的foo方法始终接收包含键'a'的字典。
  • AbstractClass(ABC, Generic[T]):把抽象类转为泛型类,T作为foo方法的参数类型占位符。
  • 子类继承时指定具体的TypedDict类型(如AbstractClass[DictWithAandB]),此时子类的foo方法参数类型与泛型参数一致,mypy会认可这种类型兼容关系。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 01:40:46