嵌套字典的类型提示

Zab*_*aba 7 python json dictionary type-hinting

在我的Python脚本的一种数据结构我分析的是一个JSON文件,该文件后json.load(file_handle),是类型<class 'dict'>。到现在为止还挺好。现在对于使用它作为输入参数的函数,我想要解析的 json 的类型提示。我在打字文档中读到,对于dicts 作为参数,我应该使用Mapping[key_type, value_type]

from typing import Mapping

def foo(json_data: Mapping[str, str]) -> None:
    ...
Run Code Online (Sandbox Code Playgroud)

我解析的 json 有str-type 键和str-type 值,但通常情况下,它的结构是高度递归的。因此,值更可能是dict带有str键的 a,甚至是dicts 作为值。它是非常嵌套的,直到在最深的层次上,最后一个 dict 终于有了str键和str值。

那么我如何更精确地表示这个数据结构呢?我在想一些事情,沿着这个问题的思路,它可能是:

Union[Mapping[str, str], Mapping[str, Mapping]]
Run Code Online (Sandbox Code Playgroud)

但它似乎只代表一级递归。有没有更好的方法来提示这个?

viv*_*vax 16

简单的词典

您可以简单地用作Mapping[K, V]另一个 的值Mapping。假设你的 json 看起来像这样:

{
   "person_1": {"money": 1000},
   "person_2": {"money": 1000}
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您可以使用如下所示的类型提示:

Mapping[str, Mapping[str, int]]
Run Code Online (Sandbox Code Playgroud)

较难的听写

但假设你有更复杂的东西,如下所示:

{
    "person_1": {
        "money": 1000,
        "job": "coder",
    }
}
Run Code Online (Sandbox Code Playgroud)

那么你怎么能输入提示呢?您可以使用Union(通过输入)来执行以下操作:

Mapping[str, Mapping[str, Union[str, int]]]
Run Code Online (Sandbox Code Playgroud)

但现在我们会遇到像 mypy Think 这样的工具的问题,其our_dict["person_1"]["job"]类型为Union[str, int]

好吧,这并没有错,毕竟我们就是这么告诉的。在这里可以提供帮助的是来自typing_extensions的TypedDict

from typing_extensions import TypedDict

class Person(TypedDict):
    money: int
    job: str

# type hint you would use in your function:
Mapping[str, Person]
Run Code Online (Sandbox Code Playgroud)

注意:在 python 3.8中是 输入TypedDict的一部分

  • 是的,我明白这一切,但我在暗示嵌套深度未知的类型时遇到问题。您给出了存在一层深度映射嵌套的示例。但我的函数需要一个参数,其中嵌套深度可以是 1 到...之间的任何值,我什至不知道有多少层,也许是 5 层,也许是 10 层?有些按键深入,有些则不然。它就像分形一样,键始终具有相同的类型联合(包括映射类型本身)。 (11认同)

Ada*_*ith 6

如今,mypy 和其他类型检查器支持递归定义。Json 类型的(某种程度上)完整示例是:

import typing as t

JsonType: t.TypeAlias = t.List['JsonValue'] | t.Mapping[str, 'JsonValue']
JsonValue: t.TypeAlias = str | int | float | None | JsonType

def foo(json_data: JsonType) -> None:
    """Your implementation here"""
Run Code Online (Sandbox Code Playgroud)

这应该进行类型检查。