mypy在__init__中报numpy参数类型错误但普通方法不报,如何解决?
mypy 未识别类方法内numpy ufunc参数类型错误的解决方案
问题差异原因
你遇到的三种场景检查结果不一致,核心来自两个原因:
- 参数类型识别范围差异
第一个类的__init__方法中参数a是显式标注的Optional[float],mypy在当前作用域可以直接识别该参数可能为None,不符合np.radians的入参类型要求,因此直接报错。 - 默认配置下实例属性类型推断宽松
第二个类的实例属性self.a没有做显式类型标注,mypy默认配置下不会严格跟踪实例属性的可空性,会放宽后续方法中对该属性的类型检查规则,因此不会触发报错。 - numpy类型存根标注宽松
直接调用np.radians(None)不报错,是因为numpy内置的类型存根对ufunc通用入参做了兼容None的宽松标注,但没有兼容Optional[float]这类联合类型,因此会出现显式传None不报错、传Optional类型反而报错的情况。
配置与修改方案
要让mypy识别第二种场景的类型错误,可以任选以下一种方案,或者组合使用获得更严格的检查效果:
方案1:显式标注实例属性类型
不需要修改mypy配置,只需要给实例属性加显式类型标注,mypy就会严格检查该属性的后续使用:
from typing import Optional import numpy as np class TestClass(): # 显式标注类属性类型,实例属性会继承该标注 a: Optional[float] def __init__(self, a: Optional[float] = None): self.a = a def test(self): # 此处会触发和第一个类一致的类型错误 b = np.radians(self.a)
方案2:修改mypy配置开启严格检查
在mypy配置文件(mypy.ini或pyproject.toml)中开启以下配置项,全局启用严格的类型检查规则:
# mypy.ini 示例配置 [mypy] # 开启严格的None检查,基础配置 strict_optional = True # 强制严格推断实例属性类型,不会放宽未标注属性的检查 strict_attribute_inference = True # 禁止未标注类型的实例属性定义 disallow_incomplete_defs = True # 禁止未标注类型的函数定义,进一步收紧检查规则 disallow_untyped_defs = True
开启配置后,就算你没有显式标注self.a的类型,mypy也会严格推断它的类型为Optional[float],在test方法中传递给np.radians时就会触发类型错误。
补充说明
如果想要让np.radians(None)也触发类型错误,可以额外开启disallow_any_expr = True配置,或者自行封装numpy方法添加严格的类型标注,覆盖原生的宽松存根规则。
内容的提问来源于stack exchange,提问作者dmmpie
相关产品推荐
相关产品推荐

