Python MyPy报incompatible types赋值类型不兼容错误如何修复
问题描述
开发过程中编写了如下Python代码:
def get_tree(args): sensor_ids = argToList(args.get("sensor_ids")) process_ids = argToList(args.get("process_ids")) all_results = {} for sensor_id in sensor_ids: sensor_id_str = str(sensor_id) for process_id in process_ids: process_id_str = str(process_id) main_process = query_process(sensor_id_str, process_id_str) results = {} json_response = main_process.json() for vertex in json_response["resources"]: if vertex["vertex_type"] == "process": results["main_process"] = {"sensor_id": sensor_id_str, "process_id": process_id_str, "properties": vertex["properties"]} for edge in vertex["edges"]: if edge == "child_process": results["child_processes"] = []
对上述代码做静态检查时,flake8未提示任何异常,但MyPy抛出如下错误:
Incompatible types in assignment (expression has type
"List[]", target has type "Dict[str, Any]") [assignment]
results["child_processes"] = []
^
报错原因
MyPy做静态类型检查时,会根据变量第一次被赋值的内容自动推断类型。代码中初始化results = {}后,第一次给results赋值的键是main_process,对应值为字典类型,MyPy会自动把results推断为「键为字符串、值为字典」的字典类型。后续给results["child_processes"]赋值列表类型的值时,就和MyPy之前推断的值类型不匹配,因此抛出类型不兼容的错误。
flake8不做严格的跨赋值语句的类型推断校验,因此不会提示该问题。
修复方案
有两种常用的无副作用修复方式:
- 显式给
results变量加类型标注,明确告知MyPy该字典的值可以是任意类型。Python 3.9及以上版本不需要额外导入模块,初始化时直接写results: dict[str, Any] = {}即可;低版本Python需要从typing模块导入Dict和Any,写为results: Dict[str, Any] = {}。 - 初始化
results字典时就提前声明所有用到的键和对应类型的默认值,比如初始化为results = {"main_process": {}, "child_processes": []},MyPy在初始化阶段就能识别到不同键对应的值类型,不会出现推断错误。
修复后的示例代码(采用显式类型标注方案):
from typing import Any, Dict def get_tree(args): sensor_ids = argToList(args.get("sensor_ids")) process_ids = argToList(args.get("process_ids")) all_results = {} for sensor_id in sensor_ids: sensor_id_str = str(sensor_id) for process_id in process_ids: process_id_str = str(process_id) main_process = query_process(sensor_id_str, process_id_str) # 显式标注类型,修正MyPy类型推断偏差 results: Dict[str, Any] = {} json_response = main_process.json() for vertex in json_response["resources"]: if vertex["vertex_type"] == "process": results["main_process"] = {"sensor_id": sensor_id_str, "process_id": process_id_str, "properties": vertex["properties"]} for edge in vertex["edges"]: if edge == "child_process": results["child_processes"] = []
内容的提问来源于stack exchange,提问作者Neil
相关产品推荐
相关产品推荐

