为何mypy不警告未定义类属性?如何强制其检测?
问题解答
1. 为什么mypy不提示属性未定义错误?
mypy作为静态类型检查工具,只会扫描类的所有方法代码逻辑:只要发现类内存在任意方法(比如这里的set_this_or_everything_breaks)给self.important_variable完成过赋值,就会默认该属性是类实例的合法属性。它无法追踪代码运行时的方法调用顺序,没法判断run被调用前有没有执行过赋值方法,因此不会触发报错。而当移除那个赋值方法后,类内没有任何地方定义过该属性,mypy才会检测到未定义问题。
2. 如何让mypy在当前代码场景下报错?
有几种可行方案:
- 开启严格初始化检查:在mypy配置文件(如
mypy.ini)中设置strict_property_initialization = True,或直接执行命令mypy --strict-property-initialization your_file.py。该选项会强制要求实例属性必须在__init__方法、类定义时的默认值,或@property装饰的方法中完成初始化。当前代码里important_variable仅在普通方法中赋值,开启检查后mypy会报错提示属性未正确初始化。 - 显式添加属性类型注解:在类A中声明属性类型,代码如下:
配合class A: important_variable: str # 显式声明属性类型 def set_this_or_everything_breaks(self) -> None: self.important_variable = "c" def run(self) -> None: print(f"this is what is important {self.important_variable.lower()}")strict_property_initialization选项,mypy会因important_variable未在初始化阶段赋值而报错。 - 启用
--strict模式:直接执行mypy --strict your_file.py,该模式包含strict_property_initialization在内的一系列严格检查规则,可直接触发该场景下的错误提示。
3. 能否强制所有类属性必须在类定义中声明?
可以通过以下方式实现:
- 启用mypy严格模式:在mypy配置中设置
strict = True,其中的strict_property_initialization会强制属性要么在类定义时声明并给出默认值,要么在__init__中初始化;同时disallow_untyped-defs会要求所有方法添加类型注解,进一步约束属性声明规范。 - 使用数据类(dataclasses):用
dataclasses.dataclass装饰器定义类,所有属性必须在类定义时声明类型,否则无法生成正确的初始化方法,mypy和Python解释器都会严格检查:
这种方式下,实例化A时必须传入from dataclasses import dataclass @dataclass class A: important_variable: str # 必须声明属性类型 def set_this_or_everything_breaks(self) -> None: self.important_variable = "c" def run(self) -> None: print(f"this is what is important {self.important_variable.lower()}")important_variable的值,否则会触发报错。 - 使用
attrs库:类似dataclasses,attrs库会强制在类定义中声明所有属性,同时提供更灵活的配置,mypy也能很好地支持这类注解。
内容的提问来源于stack exchange,提问作者asdfjlsdkfasjfowei
相关产品推荐
相关产品推荐

