Mypy对枚举类型字段的类型收窄在字段覆写后未更新的问题咨询
Mypy对枚举类型字段的类型收窄在字段覆写后未更新的问题咨询
看起来你碰到了mypy处理枚举类型实例变量时的一个类型推断小坑,我来帮你拆解下这个问题:
先还原下你的代码场景,方便大家理解:
from enum import Enum class E(Enum): A = 1 B = 2 class Test: def __init__(self) -> None: self.var = E.A def update(self, var: E) -> None: self.var = var obj = Test() assert obj.var is E.A obj.update(E.B) assert obj.var is E.B # 这里mypy报错:Non-overlapping identity check...
你提到的现象很准确:第一个assert之后,mypy确实正确把obj.var的类型收窄成了Literal[E.A],但当你调用update方法把它改成E.B后,mypy却没有更新这个变量的类型信息,依然认为它是Literal[E.A],所以第二个断言触发了类型不匹配的错误,而且非枚举类型的变量不会出现这个问题。
这到底是你的问题还是mypy的问题?
这更偏向于mypy当前的类型推断局限性,而非你的代码写法错误。mypy对于实例变量的类型收窄,在经过外部方法(哪怕是类自己的方法)修改后,默认不会自动“撤销”之前的收窄状态——尤其是枚举这种自带字面量类型的情况,mypy的类型追踪逻辑暂时没办法完美覆盖这种场景,没办法识别到方法内部对实例变量的修改,从而更新它的类型信息。
有什么解决办法吗?
给你两个实用的规避方案:
- 明确声明实例变量的类型:在
__init__里直接把self.var的类型声明为枚举基类E,而不是让mypy自动推断成字面量类型Literal[E.A]。这样mypy就不会做过于严格的字面量收窄,后续的赋值和断言就都能正常通过检查了。
修改后的代码示例:from enum import Enum class E(Enum): A = 1 B = 2 class Test: def __init__(self) -> None: self.var: E = E.A # 明确指定类型为E def update(self, var: E) -> None: self.var = var obj = Test() assert obj.var is E.A obj.update(E.B) assert obj.var is E.B # mypy不再报错 - 临时跳过检查(不推荐滥用):如果只是想快速绕过这个错误,可以在第二个断言后面加上
# type: ignore[comparison-overlap],但这种方式会跳过mypy的类型检查,尽量少用。
内容来源于stack exchange
相关产品推荐
相关产品推荐

