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

定义键值共享约束泛型的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 03:39:36