如何为递归转换SpecialDict至标准dict的函数添加正确Python类型注解?
问题:为递归转换SpecialDict的函数添加正确类型注解
我正在处理一个数据库返回的SpecialDict对象(dict的子类),它无法接收类型参数,需要转换为标准dict。我写了递归函数converter处理嵌套的SpecialDict,容器约束如下:
- 键始终为
str - 可包含其他
SpecialDict实例 - 可包含
list - 最终叶子节点为
int或str原子值
递归实现代码如下:
SUPPORTED_CONTAINER_TYPES = (dict, list) SUPPORTED_ATOMIC_TYPES = (str, int) class SpecialDict(dict): pass def converter(container): if isinstance(container, dict): dict_ = {} for key, value in container.items(): if isinstance(value, SUPPORTED_CONTAINER_TYPES): dict_[key] = converter(container=value) elif isinstance(value, SUPPORTED_ATOMIC_TYPES): dict_[key] = value else: raise TypeError(f"{type(value)} is not supported.") return dict_ if isinstance(container, list): datastore_list = [] for item in container: if isinstance(item, SUPPORTED_CONTAINER_TYPES): datastore_list.append(converter(container=item)) elif isinstance(item, SUPPORTED_ATOMIC_TYPES): datastore_list.append(item) else: raise TypeError(f"{type(item)} is not supported.") return datastore_list raise TypeError(f"{type(container)} is not supported.")
尝试添加递归类型注解时遇到多个mypy错误,无法准确表达嵌套结构的类型约束,求正确的函数类型注解方案。
解决方案
要正确标注这种递归嵌套的结构,需要使用递归类型定义,结合TypeVar和Union来描述允许的嵌套层级。以下是修改后的带类型注解的代码:
from typing import TypeVar, Union, Dict, List # 启用字符串形式的类型引用,解决递归类型的循环引用问题(Python 3.7+需要) from __future__ import annotations SUPPORTED_CONTAINER_TYPES = (dict, list) SUPPORTED_ATOMIC_TYPES = (str, int) class SpecialDict(dict): pass # 定义递归类型变量:T可以是原子类型,或者嵌套的字典/列表 T = TypeVar('T', bound=Union[str, int, 'NestedDict', 'NestedList']) # 嵌套字典:字符串键对应递归类型T NestedDict = Dict[str, T] # 嵌套列表:元素是递归类型T NestedList = List[T] def converter(container: Union[SpecialDict, NestedList]) -> Union[NestedDict, NestedList]: if isinstance(container, dict): dict_: NestedDict = {} for key, value in container.items(): if isinstance(value, SUPPORTED_CONTAINER_TYPES): dict_[key] = converter(container=value) elif isinstance(value, SUPPORTED_ATOMIC_TYPES): dict_[key] = value else: raise TypeError(f"{type(value)} is not supported.") return dict_ if isinstance(container, list): datastore_list: NestedList = [] for item in container: if isinstance(item, SUPPORTED_CONTAINER_TYPES): datastore_list.append(converter(container=item)) elif isinstance(item, SUPPORTED_ATOMIC_TYPES): datastore_list.append(item) else: raise TypeError(f"{type(item)} is not supported.") return datastore_list raise TypeError(f"{type(container)} is not supported.")
注解说明
- 递归类型定义:通过
TypeVar绑定Union[str, int, 'NestedDict', 'NestedList'],让类型系统能识别嵌套的字典和列表结构。 - 字符串类型引用:使用
'NestedDict'和'NestedList'的字符串形式,配合from __future__ import annotations避免递归类型的循环引用报错。 - 函数注解:参数
container允许接收SpecialDict或嵌套列表,返回值对应转换后的标准嵌套字典或列表,mypy可以正确推断每一层的类型。
如果使用Python 3.10+,可以用PEP 604的|语法简化类型定义:
# Python 3.10+ 简化写法 T = TypeVar('T', bound=str | int | 'NestedDict' | 'NestedList') NestedDict = Dict[str, T] NestedList = List[T]
内容的提问来源于stack exchange,提问作者Fredrik Nilsson
相关产品推荐
相关产品推荐

