Python:将变量注释为 TypedDict 的键

Sup*_*oot 16 python mypy python-typing

基本上是这个问题(尚未得到解答)的精炼版本。

我想声明的是,变量应该只采用TypedDict.

目前我正在定义一个单独的Literal类型来表示键,例如:

from typing import Literal, TypedDict


class MyTD(TypedDict):
    a: int
    b: int


mytd = MyTD(a=1, b=2)

key = "a"

mytd[key]  # error: TypedDict key must be a string literal; expected one of ('a', 'b')

MyTDKeyT = Literal["a", "b"]

typed_key: MyTDKeyT = "b"

mytd[typed_key]  # no error
Run Code Online (Sandbox Code Playgroud)

我希望能够Literal出于想要最小化重复代码的所有常见原因替换定义。

伪代码:

key: Keys[MyTD] = "a"
mytd[key]  # would be no error
not_key: Keys[MyTD] = "z"  # error
Run Code Online (Sandbox Code Playgroud)

有办法实现这一点吗?

为了澄清,鉴于 mypy 可以告诉我键类型需要是“a”或“b”的文字,我希望可能有一种不太容易出错的方法来将变量注释为该类型,而不是使用并排维护两个单独的键列表,一次在定义中TypedDict,一次在Literal定义中。

Ray*_*ger 3

使用 MyPy,我认为这是不可能的。我进行了这个实验:

from typing import TypedDict

class MyTD(TypedDict):
    a: str
    b: int

d = MyTD(a='x', b=2)
reveal_type(list(d))
Run Code Online (Sandbox Code Playgroud)

MyPy 的输出是:

Revealed type is "builtins.list[builtins.str]"
Run Code Online (Sandbox Code Playgroud)

这表明它在内部没有将键作为文字进行跟踪。否则,我们会期望:

Revealed type is "builtins.list[Literal['A', 'B']]" 
Run Code Online (Sandbox Code Playgroud)

另外,这个错误在 MyPy 中出现,所以__required_keys__甚至无法检查:

reveal_type(MyTD.__required_keys__)
Run Code Online (Sandbox Code Playgroud)

  • 感谢您抽出时间,雷蒙德 - 这是有道理的。感觉像是错失了机会——但你可以用我不知道的东西编写一个完整的静态类型系统。鉴于 PEP 589 中的一个想法没有被拒绝,我将生活在希望之中。 (2认同)