You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何mypy无法识别原始元组为NamedTuple类型?

问题原因与解决方法

现象回顾

使用NamedTuple作为字典键类型时,传入普通元组会触发mypy类型错误:

from typing import NamedTuple

class KeyTuple(NamedTuple):
    key: str

storage: dict[KeyTuple, int] = {}

storage.get(("kek",))  # mypy报错

错误信息:

test_mypy.py:8: error: No overload variant of "get" of "dict" matches argument type "Tuple[str]" [call-overload]
test_mypy.py:8: note: Possible overload variants:
test_mypy.py:8: note: def get(self, KeyTuple, /) -> Optional[int]
test_mypy.py:8: note: def [_T] get(self, KeyTuple, Union[int, _T], /) -> Union[int, _T]

但直接使用tuple[str]作为键类型时,相同的元组调用不会报错:

storage: dict[tuple[str], int] = {}

storage.get(("kek",))  # mypy无错误

原因分析

虽然KeyTuple继承自tuple,但mypy将其视为独立的自定义类型,而非tuple[str]的兼容类型。普通元组("kek",)的类型是tuple[str],和KeyTuple属于不同的类型范畴,因此无法匹配字典get方法要求的KeyTuple参数类型。

而当字典键类型直接定义为tuple[str]时,("kek",)的类型正好符合要求,所以不会触发错误。

解决方案

要解决这个问题,需要传入真正的KeyTuple实例,而不是普通元组:

from typing import NamedTuple

class KeyTuple(NamedTuple):
    key: str

storage: dict[KeyTuple, int] = {}

storage.get(KeyTuple("kek"))  # 正确,mypy无错误

如果确实需要兼容普通元组的传入(不推荐,会破坏类型安全性),可以显式进行类型转换:

storage.get(KeyTuple(*("kek",)))

内容的提问来源于stack exchange,提问作者Leydenberg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 19:35:25