mypy 设置字典键/界面

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

假设我有一个以字典作为参数的函数:

def f(d: dict) -> None:
    x = d["x"]
    print(x)

我可以指定这个字典必须有mypy的密钥

"x"
吗?我正在寻找类似于 typescript 的界面,而不将
d
更改为类。

我不想将

d
更改为类的原因是因为我正在修改大型现有代码库以添加
mypy
类型检查,并且该字典在很多地方使用。如果我必须将
d["x"]
的所有实例更改为
d.x
,我就必须修改大量代码。

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

从 Python 3.8 开始,您可以使用

typing.TypedDict
,根据 PEP 589 添加。对于较旧的 Python 版本,您可以使用
typing-extensions

请注意,PEP 确实承认更好的选择是针对此用例使用 dataclasses,但是:

数据类是解决此用例的最新替代方案,但仍然有许多现有代码是在数据类可用之前编写的,特别是在类型提示和检查已被证明很有帮助的大型现有代码库中。

因此,更好的答案是考虑不同的数据结构,例如命名元组或数据类,您可以在其中指定类型具有的属性。这就是打字稿声明的作用,真的:

printLabel

函数有一个参数,要求传入的对象有一个名为
label
的字符串类型的属性。

Python 属性在道德上等同于 Typescript 对象属性。 Typescript 对象表示法和 Python 字典有很多共同点,这可能会让人感到困惑,但是在尝试将概念映射到 Python 时,您不应该将 Typescript 对象声明视为类以外的任何东西。

可能看起来像这样:

from dataclasses import dataclass @dataclass class SomeClass: x: str def f(sc: SomeClass) -> None: x = sc.x print(x)

也就是说,您可以在这里使用

typing.TypedDict

from typing import TypedDict class SomeDict(TypedDict): x: str def f(d: SomeDict) -> None: x = d['x'] print(x)

TypeDict

声明中的键要么都是必需的,要么都是可选的(当您在声明上设置
total=False
时);您必须使用继承来生成带有某些可选键的类型,请参阅链接的文档。请注意,
TypedDict
目前存在可选键和必需键组合的问题;即使使用 Python 3.8,您也可能希望使用 typing-extensions
 包来获取 Python 3.9 版本(修复了此问题)作为向后移植。只需使用 
from typing_extensions import TypedDict
 而不是上面的 
from typing ...
 导入,
typing-extensions
 包就会在适当的时候回退到标准库版本。


3
投票
Mypy 通过提供

TypedDict

 类型扩展了 PEP 484。这允许指定字典类型的特定属性。根据您的情况,您可以执行以下操作:

from mypy_extensions import TypedDict # you can also do HasX = TypedDict('HasX', {'x': str}) class HasX(TypedDict): x: str def f(x: HasX) -> None: reveal_type(d["x"]) # error: Revealed type is 'builtins.str'
    
© www.soinside.com 2019 - 2024. All rights reserved.