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
相关产品推荐
相关产品推荐

