如何为类型映射同类型返回函数的字典添加Mypy类型注解
解决方案
要实现字典键类型与可调用对象返回类型的静态绑定,避免使用typing.Any,可以通过typing.Protocol定义字典的行为,让Mypy能精确推断每个键对应的返回类型。
方法一:使用Protocol(推荐)
这种方法能让Mypy自动关联键类型和返回类型,无需额外类型断言:
from typing import Protocol, TypeVar, Callable # 定义类型变量,约束为需要处理的目标类型 T = TypeVar('T', bytes, int, str) # 定义协议,描述字典的索引行为:输入类型对象,返回对应类型的转换器 class TypeConverter(Protocol): def __getitem__(self, key: type[T]) -> Callable[[bytes], T]: ... # 给字典添加类型注解 MY_DICT: TypeConverter = { bytes: lambda x: x, int: lambda x: int.from_bytes(x, 'big'), str: lambda x: x.decode('utf-8'), }
效果说明
- 访问
MY_DICT[bytes]时,Mypy会自动推断其类型为Callable[[bytes], bytes] - 访问
MY_DICT[int]时,推断为Callable[[bytes], int] - 完全实现静态类型检查,无
Any的模糊性
方法二:显式联合类型(不推荐)
如果不想使用Protocol,也可以直接指定字典的类型为联合的键值对组合,但访问时Mypy会返回联合类型,需手动添加类型断言才能获得精确类型:
from typing import Callable, Type, Union, cast # 定义联合类型的字典 ConverterDict = dict[ Union[Type[bytes], Type[int], Type[str]], Union[ Callable[[bytes], bytes], Callable[[bytes], int], Callable[[bytes], str] ] ] MY_DICT: ConverterDict = { bytes: lambda x: x, int: lambda x: int.from_bytes(x, 'big'), str: lambda x: x.decode('utf-8'), } # 访问时需要类型断言才能获得精确类型 bytes_converter = cast(Callable[[bytes], bytes], MY_DICT[bytes])
缺点
- 每次访问字典元素都需要手动断言,代码冗余
- Mypy无法自动关联键和返回类型,损失部分静态检查优势
内容的提问来源于stack exchange,提问作者Ryan Collingham
相关产品推荐
相关产品推荐

