如何为任意深度的递归defaultdict添加正确的类型注解?
修复递归defaultdict的mypy类型报错问题
你的问题出在defaultdict是泛型类型,mypy要求必须显式指定它的键类型和值类型参数,而原代码的返回值标注仅写了defaultdict,缺少泛型参数,因此触发报错。以下是两种可行的修复方案,均能保留任意深度嵌套和任意值类型的能力:
方案一:使用递归类型别名(Python 3.10+)
这是最简洁的方案,利用Python 3.10支持的递归类型别名,直接定义递归字典的类型:
from collections import defaultdict from datetime import datetime from typing import Any, TypeAlias # 定义递归类型:键为字符串,值可以是递归字典或任意类型 RecursiveDict: TypeAlias = defaultdict[str, "RecursiveDict | Any"] def recursive_dict() -> RecursiveDict: """enable arbitrary depth dictionary declaration""" return defaultdict(recursive_dict) dbdict = recursive_dict() dbdict["entity"]["surface"] = "this is a string" dbdict["entity"]["spotlight"]["uri"] = "http://test.com/test" dbdict["entity"]["spotlight"]["curation"]["date"] = datetime.now()
方案二:使用泛型类兼容旧版本Python(Python 3.9及以下)
如果你的项目需要兼容Python 3.9或更早版本,可以用Generic和TypeVar来定义递归结构:
from collections import defaultdict from datetime import datetime from typing import Any, Generic, TypeVar T = TypeVar("T") class RecursiveDict(Generic[T], defaultdict[str, "RecursiveDict[T] | T"]): pass def recursive_dict() -> RecursiveDict[Any]: """enable arbitrary depth dictionary declaration""" return RecursiveDict(recursive_dict) dbdict = recursive_dict() dbdict["entity"]["surface"] = "this is a string" dbdict["entity"]["spotlight"]["uri"] = "http://test.com/test" dbdict["entity"]["spotlight"]["curation"]["date"] = datetime.now()
说明
两种方案都明确了defaultdict的键类型为str(匹配你代码中使用字符串作为键的场景),值类型允许是递归字典或任意类型(Any),既满足mypy的类型检查要求,又完全保留了你原代码的功能——可以无限嵌套字典,同时每个节点可以存储任意类型的值(字符串、datetime等)。
内容的提问来源于stack exchange,提问作者Robert Alexander
相关产品推荐
相关产品推荐

