如何为UserDict提供类型提示?

问题描述 投票:0回答:1

我想定义一个

UserDict
来从 JSON 读取值并存储给定键的位置。 JSON 文件如下所示:

{
    "pages": [
        {
            "areas": [
                {
                    "name": "My_Name",
                    "x": 179.95495495495493,
                    "y": 117.92792792792793,
                    "height": 15.315315315315303,
                    "width": 125.58558558558553
                },
                ...
              ]
        }
    ]
}

我想向类型 linter(例如 MyPy)表明该字典作为键是字符串,值是

Position

我当前的代码如下:

import json
from collections import UserDict
from dataclasses import dataclass, field
from pathlib import Path
from typing import Dict, List, Optional, Union

from typing_extensions import Literal


JsonPosition = Dict[str, Union[str, float]]
JsonPage = Optional[Dict[Literal["areas"], List[JsonPosition]]]


@dataclass
class Position:
    """Information for a position"""

    name: str
    x: float
    y: float
    width: float
    height: float

    @classmethod
    def from_json(cls, dict_values: JsonPosition):
        return cls(**dict_values)  # type: ignore  # dynamic typing


class Page(UserDict):
    """Information about positions on a page"""

    @classmethod
    def from_json(cls, page: JsonPage):
        """Get positions from JSON Dictionary"""
        if page is None:
            return cls()

        return cls({cast(str, p["name"]): Position.from_json(p) for p in page["areas"]})



JSON = Path("my_positions.json").read_text()
positions = json.loads(JSON)
page_1 = Page.from_json(positions["pages"][0])

我希望 MyPy(或 Pylance 或我使用的任何类型提示)自动将

page_1["My_Name"]
识别为
Position

我可以改变什么?

python mypy python-typing
1个回答
5
投票

实际上,您可以直接使用方括号 (

UserDict
) 向
[...]
提供类型,就像使用
Dict
一样:

class Page(UserDict[str, Position]):
    ...

对于 Python 3.6 或更早版本,这将不起作用。

对于 Python >=3.7 和 <3.9,您需要 以下

collections.UserDict
下标,并将其放入特定于类型检查的单独块中(使用常量
TYPE_CHECKING
):

from __future__ import annotations
from collections import UserDict
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    TypedUserDict = UserDict[str, Position]
else:
    TypedUserDict = UserDict


class Page(TypedUserDict):
    ...

对于 Python 3.9+,不需要额外的导入或技巧。

© www.soinside.com 2019 - 2024. All rights reserved.