带泛型的 Python TypedDict
原文由 Alex O'Callaghan 于 发布,订阅该博客
Python 在 3.5 中加入了对类型提示的支持,但要用泛型来标注 dict 值的类型,却出乎意料地棘手。
如果字典的键是固定的,使用 typing 模块中的 TypedDict 类来定义类型提示就相当简单:
from typing import TypedDict
class Book(TypedDict):
id: int
name: str
book: Book = {"id": 123, "name": "To Kill A Mockingbird"}如果再加上一行:
not_a_book: Book = {"something": "A book doesn't have"}再用 mypy 检查,会得到:
$ python -m mypy type-dict.py
type-dict.py:9: error: Missing keys ("id", "name") for TypedDict "Book" [typeddict-item]
type-dict.py:9: error: Extra key "something" for TypedDict "Book" [typeddict-unknown-key]
Found 2 errors in 1 file (checked 1 source file)很简单吧!
typing 模块还提供了 Generic 和 TypeVar 来支持泛型类。在我的场景中,我想为一个嵌套的 dict 定义一个泛型类,其中 value 键的类型是可变的。沿用上面的 book 示例:
from typing import TypeVar, Generic, TypedDict
T = TypeVar('T')
class Attribute(TypedDict, Generic[T]):
value: T
class Book(TypedDict):
id: Attribute[int]
name: Attribute[str]
book: Book = {"id": {"value": 123}, "name": {"value": "To Kill A Mockingbird"}}用 mypy 做类型检查,一切正常!不过试着直接运行一下……
$ python --version
Python 3.10.12
$ python type-dict-generic.py
Traceback (most recent call last):
File "/home/aocallaghan/exp/py-type-dict/type-dict-generic.py", line 5, in <module>
class Attribute(TypedDict, Generic[T]):
File "/home/aocallaghan/.pyenv/versions/3.10.12/lib/python3.10/typing.py", line 2348, in __new__
raise TypeError('cannot inherit from both a TypedDict type '
TypeError: cannot inherit from both a TypedDict type and a non-TypedDict base class在 Python 3.10 中,你不能同时继承 TypedDict 类型和其他基类。不过这个问题在 Python 3.11 中已经被修复:
$ python --version
Python 3.11.4
$ python type-dict-generic.py遗憾的是,在 3.11 之前的版本中似乎没有简单的实现方法。一种替代方案是使用 Enum 类来表示键:
from enum import Enum, auto
from typing import TypeVar, TypedDict
T = TypeVar('T')
class AttributeKeys(Enum):
value = auto()
class Book(TypedDict):
id: dict[AttributeKeys, int]
name: dict[AttributeKeys, str]
book: Book = {"id": {AttributeKeys.value: 123}, "name": {AttributeKeys.value: "To Kill A Mockingbird"}}
not_a_book: Book = {"something": "A book doesn't have"}随机一篇博客
评论
登录后参与讨论