从函数的关键字参数生成 TypedDict

Mar*_*hac 6 python type-hinting mypy

foo.py

kwargs = {"a": 1, "b": "c"}

def consume(*, a: int, b: str) -> None:
    pass

consume(**kwargs)
Run Code Online (Sandbox Code Playgroud)

mypy foo.py

error: Argument 1 to "consume" has incompatible type "**Dict[str, object]"; expected "int"
error: Argument 1 to "consume" has incompatible type "**Dict[str, object]"; expected "str"
Run Code Online (Sandbox Code Playgroud)

这是因为objectintand的超类型,str因此被推断出来。如果我声明:

from typing import TypedDict

class KWArgs(TypedDict):
    a: int
    b: str
Run Code Online (Sandbox Code Playgroud)

然后注释kwargsKWArgsmypy检查通过。这实现了类型安全,但需要我复制consumein的关键字参数名称和类型KWArgs。有没有办法TypedDict在类型检查时从函数签名中生成它,以便我可以最大限度地减少维护中的重复?

Mar*_*hac 5

这将通过PEP 692在 Python 3.12 中提供:

from typing import TypedDict, Unpack, Required, NotRequired

class KWArgs(TypedDict):
    a: Required[int]
    b: NotRequired[str]

def consume(**kwargs: Unpack[KWArgs]) -> None:
    a = kwargs["a"]
    b = kwargs.get("b", ...)

consume()              # Not allowed.
consume(a=1)           # Allowed.
consume(a=1, b="abc")  # Allowed.
Run Code Online (Sandbox Code Playgroud)