Mypy问题:如何在子类中特化属性的类型?
子类重写属性类型后,父类构造方法未触发类型检查的问题
我想让父类Parent的x属性接受Literal["a", "b", "c"]类型的值,子类Child继承自Parent,且Child的x属性仅能接受"a"。但按照下面的代码实现,实例化Child("c")时,开启--strict标志的mypy 1.3.0并未报错:
from typing import Literal class Parent: x: Literal["a", "b", "c"] def __init__(self, x: Literal["a", "b", "c"]) -> None: self.x = x class Child(Parent): x: Literal["a"] child = Child("c") # 此处应报错,但实际未报错
问题原因
你只重写了子类Child的x属性类型声明,但没有重写__init__方法。实例化Child时调用的是父类Parent的构造函数,而父类的__init__允许x传入"a"/"b"/"c",所以mypy认为这个调用是合法的,不会触发错误。
解决方法
重写子类的__init__方法,把参数x的类型限制为Literal["a"],这样mypy就会按照子类的构造方法进行类型校验:
from typing import Literal class Parent: x: Literal["a", "b", "c"] def __init__(self, x: Literal["a", "b", "c"]) -> None: self.x = x class Child(Parent): x: Literal["a"] def __init__(self, x: Literal["a"]) -> None: super().__init__(x) child = Child("c") # mypy报错:Argument 1 to "Child" has incompatible type "Literal['c']"; expected "Literal['a']"
修改后,mypy会正确识别传入"c"不符合子类的参数要求,给出错误提示。如果需要在运行时也确保x的取值合法,可以在子类的__init__中添加额外的判断逻辑,不过类型检查已经能在编译阶段拦截大部分非法输入。
内容的提问来源于stack exchange,提问作者MyUsername112358
相关产品推荐
相关产品推荐

