python - 是否有适用于字符串键控、嵌套 JSONish dicts 的 python 类型注释?
问题描述
我想在我的项目中对某些数据结构进行类型注释,这些数据结构是解码一些 JSON 数据的结果。
叶很简单:
ValueType = Union[int,str,float]
键只是字符串,所以这也很容易:
str
但问题是我的结构可以嵌套,所以我想做类似以下的事情(但没有明显失败的自引用):
ValueType = Union[int,str,float]
NestedDictType = Mapping[str,Union[NestedDictType,ValueType]] # Fails!
我想我可以在一个循环中构建一些东西,但是做这样的事情(疯狂)基本上会破坏类型注释的意义,因为 NestedDictType 的结构不能静态确定。
from typing import Mapping, Type, Union
ValueType = Union[int, str, float]
def make_nested_dict_type(depth: int) -> Type:
# Does not actually work, sorry!
valueType = Union[make_nested_dict_type(depth - 1)] if depth else ValueType
return Mapping[str, valueType]
NestedDictType: Type = make_nested_dict_type(4)
foo: NestedDictType = {"a": {"b": {"c": 3, "d": "four", "e": 5.6}}}
那么如何才能简洁地写出这种类型注解呢?
解决方案
从 Python 3.7 开始,这似乎不是 100% 实用的:
类型系统可以定义递归类型结构(使用字符串前向引用),但是,MyPy 和 PyCharm 处理类型的递归部分,就好像它们是Any一样。
我能得到的最接近的是手动将递归类型扩展到多个级别。这是一个部分成功的例子。
import datetime
from typing import Mapping, Union, Any
# Recursive structure has been manually expanded to 3 levels, with the forward ref removed.
NestedDictType = Mapping[str,Union[int,str,float,Mapping[str,Union[int,str,float,Mapping[str,Union[int,str,float,Any]]]]]]
# MyPy correctly determines that this is valid
foo: NestedDictType = {"a": {"b": {"c": 3, "d": "four", "e": datetime.date.today()}}}
# MyPy correctly determines that this is bogus
bar: NestedDictType = {"a": datetime.date.today()}
# MyPy cannot detect the error because it's > 3 depth
baz: NestedDictType = {"a":{"b":{"c":{"d":datetime.date.today()}}}}
推荐阅读
- python - Flask WTForms 用变量自动填充 StringField
- reactjs - 将 webpack-stream 与 gulp 一起使用时的奇怪行为
- powershell - 使用 powershell 获取对 Active Directory 分发列表的最新更改
- sas - sas ods --> ppt 总是'修复消息'
- c# - 无法将类型“void”隐式转换为“string”
- puppet - 为什么puppet中的exec资源的previous_value总是notrun?
- gradle - Gradle:shadowJar 将依赖项排除在外
- c++ - 条件变量中的 gcc 错误::wait_for
- mysql - 试图将西里尔符号插入 mysql 表
- vue.js - 使用动态 vue 输入的新值