定义键值共享约束泛型的Dict时mypy报类型变量未绑定如何修复
问题原因
直接在模块顶层声明d: Dict[Type[AT], List[AT]] = {}会触发mypy的未绑定类型变量错误,核心原因有两点:
- mypy要求
TypeVar定义的类型变量必须绑定在明确的作用域中:要么作为泛型类的类型参数(通过继承Generic[AT]绑定),要么作为泛型函数的签名参数绑定,不允许在全局变量注解中直接使用未绑定的泛型参数。 - 内置
Dict类型的泛型参数仅能约束所有键、所有值的整体类型范围,无法表达「单个键和对应值共享同一个具体类型」这种逐键值对的关联约束——就算强行绕过检查,用Dict[Type[A], List[A]]也只能限制键是A的子类、值是A子类的列表,不会校验键B对应的列表是不是List[B],错配成List[C]也不会触发报错。
正确修复方案
自定义泛型字典类绑定类型变量,通过类的方法/魔术方法强制键值类型匹配,代码实现如下:
from typing import Dict, Generic, TypeVar, Type, List, Any class A: pass class B(A): pass class C(A): pass AT = TypeVar("AT", bound=A) class TypedGroupDict(Generic[AT]): def __init__(self) -> None: # 内部用无类型约束的原生字典存实际数据,对外方法做类型校验 self._store: Dict[Type[Any], List[Any]] = {} def __setitem__(self, key: Type[AT], value: List[AT]) -> None: """支持下标赋值,写入时强制键值类型匹配""" self._store[key] = value def __getitem__(self, key: Type[AT]) -> List[AT]: """支持下标读取,返回值自动匹配键对应的类型""" return self._store[key] # 实例化泛型字典,指定泛型上界为A d: TypedGroupDict[A] = TypedGroupDict() # 合法操作:mypy检查通过 d[B] = [B(), B()] d[C] = [C()] b_objs: List[B] = d[B] # 类型推导正确,无需强制转换 # 非法操作:mypy直接抛出类型错误 # d[B] = [C()] # 期望List[B],实际传入List[C],检查不通过
如果不需要下标访问的语法,也可以把__setitem__/__getitem__换成普通的put/get方法,类型约束逻辑完全一致。
内容的提问来源于stack exchange,提问作者HiroIshida
相关产品推荐
相关产品推荐

