为何mypy认为键值更受限的Mapping与更宽松的Mapping不兼容?
为什么
Mapping[str, int]与Mapping[str | bytes, str | bytes | int | float]类型不兼容? 触发错误的代码
from collections.abc import Mapping def f(a: Mapping[str | bytes, str | bytes | int | float]): print(a) x: Mapping[str, int] = {'a': 1} f(x)
mypy错误信息
file.py:8: error: Argument 1 to "f" has incompatible type "Mapping[str, int]"; expected "Mapping[str | bytes, str | bytes | int | float]" [arg-type] f(x) ^ Found 1 error in 1 file (checked 1 source file)
可行修复方案
from collections.abc import Mapping def f(a: Mapping[str | bytes, str | bytes | int | float]): print(a) x: Mapping[str | bytes, int] = {'a': 1} f(x)
类型不兼容的原因
问题核心在映射的键类型匹配上:
- 函数
f声明接受的Mapping键类型是str | bytes,这意味着函数内部完全可能尝试用bytes类型的键去访问传入的映射(比如执行a[b'bar']这类操作)。 - 但你传入的
Mapping[str, int]只支持str类型的键,不接受bytes键——如果函数真的用bytes键访问,运行时会抛出KeyError,属于类型不安全的操作,因此mypy会报错。
至于值的类型是完全兼容的:int是str | bytes | int | float的子集,函数读取到的int值符合它的类型预期。
修复方案中把x的类型改为Mapping[str | bytes, int],相当于声明这个映射可以接受str或bytes类型的键,这样函数f内部无论用哪种类型的键访问都是安全的,类型自然就兼容了。
内容的提问来源于stack exchange,提问作者Yevhen Yevsyuhov
相关产品推荐
相关产品推荐

