Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

python - Type hint for nested dict

The kind of data structure I parse in my Python script is a json file which, after json.load(file_handle), is of type <class 'dict'>. So far so good. Now for a function using it as an input argument, I want a type hint for the parsed json. I read in the typing documentation, that for dicts as arguments, I should use Mapping[key_type, value_type]:

from typing import Mapping

def foo(json_data: Mapping[str, str]) -> None:
    ...

The json I parse has str-type keys and str-type values, but more often than not, its structure is highly recursive. Hence a value is more likely to be a dict with str keys and even such dicts as values. It is very nested, until, at the deepest level, the last dict finally has str keys and str values.

So how do I represent this data structure more precisely? I was thinking something, along the lines of this question, that it might be:

Union[Mapping[str, str], Mapping[str, Mapping]]

But it does seem to represent only one level of recursion. Is there a better way to type-hint this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

simple dicts

you can simply use Mapping[K, V] as the value for another Mapping. let's say your json looks like this:

{
   "person_1": {"money": 1000},
   "person_2": {"money": 1000}
}

in this case you can use a type hint that looks like this:

Mapping[str, Mapping[str, int]]

harder dicts

but let's say you have something more complex, like this:

{
    "person_1": {
        "money": 1000,
        "job": "coder",
    }
}

how could you type hint this then? you can use Union (from typing) to do something like this:

Mapping[str, Mapping[str, Union[str, int]]]

but now we would run into a problem with tools like mypy thinking that our_dict["person_1"]["job"] has the type Union[str, int]

well it is not wrong, that is what we told it after all. something that could help here is TypedDict from typing_extensions.

from typing_extensions import TypedDict

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

# type hint you would use in your function:
Mapping[str, Person]

NOTE: in python 3.8 TypedDict is part of typing


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...