Python递归自定义Json类型赋值异常问题求助
递归JSON类型定义的类型检查问题及解决方法
问题描述
采用递归方式定义JSON类型时,出现了类型校验不一致的情况:直接使用字面量[0., 0.]赋值能通过检查,但用变量或[0.] * 2生成的列表赋值时却报错。按逻辑所有情况都应该通过校验,想知道这是不是bug,以及有没有无需给类型定义加冗余检测的解决办法。
代码示例
import typing as t JsonType: t.TypeAlias = t.List['JsonValue'] | t.Mapping[str, 'JsonValue'] JsonValue: t.TypeAlias = str | int | float | None | JsonType v0 = [0., 0.] # (variable) v0: list[float] v1 = [0.] * 2 # (variable) v1: list[float] test01: JsonType = { "v0": [0., 0.] # ok } test02: JsonType = { "v0": v0 # error } test11: JsonType = { "v": [0.] * 2 # error } test12: JsonType = { "v": v1 # error }
错误信息
表达式类型 "dict[str, list[float]]" 与声明类型 "JsonType" 不兼容 类型 "dict[str, list[float]]" 与类型 "JsonType" 不兼容 "dict[str, list[float]]" 与 "List[JsonValue]" 不兼容 "dict[str, list[float]]" 与 "Mapping[str, JsonValue]" 不兼容 类型参数 "_VT_co@Mapping" 是协变的,但 "list[float]" 不是 "JsonValue" 的子类型 类型 "list[float]" 与类型 "JsonValue" 不兼容 "list[float]" 与 "str" 不兼容 "list[float]" 与 "int" 不兼容 "list[float]" 与 "float" 不兼容 ...PylancereportAssignmentType
问题原因
这不是bug,是静态类型检查器(比如Pylance)对字面量类型推导和变量类型推导的处理逻辑差异导致的:
- 直接写字面量时,检查器会在赋值场景下尝试向上兼容递归定义的
JsonValue类型,允许list[float]隐式匹配List[JsonValue]; - 对于变量或
[0.] * 2这类表达式,检查器会推导出精确的list[float]类型,而递归定义的JsonType里的List[JsonValue]要求元素必须是JsonValue,由于list[float]没有被显式关联到JsonValue,检查器无法自动完成兼容匹配。
解决方法(无需冗余类型检查)
1. 给变量显式标注JsonValue类型
直接给变量指定类型,让检查器明确它属于JsonValue:
import typing as t JsonType: t.TypeAlias = t.List['JsonValue'] | t.Mapping[str, 'JsonValue'] JsonValue: t.TypeAlias = str | int | float | None | JsonType v0: JsonValue = [0., 0.] v1: JsonValue = [0.] * 2 test02: JsonType = { "v0": v0 # 正常通过检查 } test12: JsonType = { "v": v1 # 正常通过检查 }
2. 用t.cast做临时类型转换
对于[0.] * 2这类临时表达式,用typing.cast告诉检查器该值符合JsonValue类型:
test11: JsonType = { "v": t.cast(JsonValue, [0.] * 2) }
3. 调整类型定义以兼容协变
如果不想每次都标注或转换,可以修改类型定义,让列表的元素类型更宽松:
JsonType: t.TypeAlias = t.List[t.Union[JsonValue, float]] | t.Mapping[str, JsonValue]
这种方式会稍微扩大类型范围,需根据实际场景判断是否适用。
内容的提问来源于Stack Exchange,提问作者Craig Hicks
相关产品推荐
相关产品推荐

