首页 > 解决方案 > 如何创建通过多个别名定义的递归 Python 类型?

问题描述

我想要这个逻辑类型结构:

from typing import List, Dict, Union

ObjectType = Dict[str, 'EntryType']
ListType = List['EntryType']
EntryType = Union[str, 'ListType', 'ObjectType']

mypy报告这些错误:

mdl/structure.py:7: error: Cannot resolve name "ObjectType" (possible cyclic definition)
mdl/structure.py:7: error: Cannot resolve name "EntryType" (possible cyclic definition)
mdl/structure.py:8: error: Cannot resolve name "ListType" (possible cyclic definition)
...

有没有办法对这种递归数据类型进行编码?

我相信我可以内联各个类型,每次都输入完整的定义,以允许递归。我宁愿避免这种情况,因为它体积庞大且不太清晰。

标签: pythontype-hintingmypypython-typing

解决方案


mypy 尚不支持递归类型。虽然他们肯定在路线图上,但我不确定何时开始实施工作。它原定于今年早些时候开始,但语义分析阶段的先决条件重构(它进行了很多内部更改以干净地支持递归类型)最终花费的时间比预期的要长,所以我不确定新的时间线是。也许在未来半年左右的某个时候?

您可以研究的一种可能的替代方法是使用TypedDicts,它可以让您将特定类型分配给某些键。如果您已经提前知道输入字典的结构是什么,这将特别有用——如果您确切知道您的 ObjectTypes 将具有哪些键,以及它们将映射到什么。如果您更喜欢使用对象而不是字典并且不想编写一堆验证逻辑,那么像pydantic这样的库在这里也很有帮助。

不过,务实地说,如果您的 dict 结构是真正的自由格式,那么最好只使用ObjectType = Dict[str, object]. 毕竟,为了准确识别您正在处理的 EntryType,您将不得不添加一些 isinstance 检查以适当地缩小类型。因此,虽然从而object不是开始Union[str, ListType, ObjectType]会有点烦人,但根据您正在做的事情,它可能不会太大。


推荐阅读