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

mypy不识别动态键的assert校验报union-attr错误如何解决?

问题原因

mypy对字典取值的类型窄化有明确的限制:当使用字面量字符串作为键取值时,mypy可以确认前后两次访问的是同一个字典键,因此assert后的类型窄化会生效;但当使用动态变量(包括列表取元素、普通变量)作为键取值时,mypy不会默认保留窄化结果——它无法确认两次索引时使用的键值完全相同,也无法确认两次访问之间字典的对应值没有被修改,因此认为你第二次访问dict2[keys[0]]时仍然是Union[str, List[str]]类型,才会报没有append方法的错误。

解决方案

最通用且不改变运行逻辑的调整方式是:将字典对应键的值先提取为局部变量,再对局部变量做类型检查,mypy对局部变量的类型窄化是完全支持的,不会有上述限制。

修改后的_func1代码如下:

from typing import Dict, List, Union


def _func1(do_something: bool) -> Dict[str, Dict[str, Union[str, List[str]]]]:
    dict1: Dict[str, Union[str, List[str]]] = dict()
    dict2: Dict[str, Union[str, List[str]]] = dict()
    dict3: Dict[str, Union[str, List[str]]] = dict()
    keys: List[str] = ['key1']
    if (do_something):
        dict1['key1'] = 'string1'
        target_key = keys[0]
        if target_key not in dict2:
            dict2[target_key] = list()
        # 提取为局部变量后做类型检查
        target_val = dict2[target_key]
        assert isinstance(target_val, list)
        target_val.append('otherstring')
    return {'outer_key_1': dict1, 'outer_key_2': dict2, 'outer_key_3': dict3}

其他可选方案

如果你确定该位置的类型一定是列表,不需要运行时检查,也可以使用typing.cast强制指定类型:

from typing import cast
# 省略其他上下文代码
cast(List[str], dict2[keys[0]]).append('otherstring')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 09:45:04