如何在Python 3.6中使用不同值类型的Dict进行静态类型检查?

sor*_*tas 3 python static-typing python-3.x mypy

尝试在Python代码中使用静态类型,这样mypy可以帮助我解决一些隐藏的错误.使用单个变量非常简单

real_hour: int = lower_hour + hour_iterator
Run Code Online (Sandbox Code Playgroud)

更难以将它与列表和词典一起使用,需要导入额外的typing库:

from typing import Dict, List
hour_dict: Dict[str, str] = {"test_key": "test_value"}
Run Code Online (Sandbox Code Playgroud)

但主要问题 - 如何使用不同值类型的Dicts,如:

hour_dict = {"test_key": "test_value", "test_keywords": ["test_1","test_2"]}
Run Code Online (Sandbox Code Playgroud)

如果我不对这样的词典使用静态类型 - mypy会显示错误,例如:

len(hour_dict['test_keywords'])
- Argument 1 to "len" has incompatible type
Run Code Online (Sandbox Code Playgroud)

那么,我的问题是:如何在这些词典中添加静态类型?:)

Mic*_*x2a 6

虽然使用Union确实是一种方法,但更精确的解决方案是使用(当前是实验性的)TypedDict类型,它允许您为每个字符串键分配特定类型。

为了使用这种类型,您必须首先mypy_extensions使用 pip 安装第 3 方库。然后您可以执行以下操作:

from typing import List
from mypy_extensions import TypedDict

MyDictType = TypedDict('MyDictType', {
        'test_key': str, 
        'test_keywords': List[str],
})

hour_dict: MyDictType = {
    "test_key": "test_value", 
    "test_keywords": ["test_1","test_2"]
}
Run Code Online (Sandbox Code Playgroud)

请注意,我们需要明确表示hour_dict属于类型MyDictType。执行此操作的一种稍微简洁的方法是用作MyDictType构造函数 - 在运行时,MyDictType(...)与doing完全相同dict(...),这意味着下面的代码的行为与上面的完全相同:

hour_dict = MyDictType(
    test_key="test_value", 
    test_keywords=["test_1","test_2"]
)
Run Code Online (Sandbox Code Playgroud)

最后,请注意使用 TypedDict 有一些限制:

  1. 仅当字典包含编译时已知类型的特定键时它才有用 -Dict[...]如果您期望真正的动态字典,则应该使用常规。
  2. 键必须都是字符串。
  3. 目前,这种类型只有 mypy 可以理解(尽管我知道有计划最终将 TypedDict 添加到 PEP 484,一旦它经过更多的实际测试,这意味着任何符合 PEP 484 的类型检查器都需要支持它)。

TypedDict旨在让编写序列化/反序列化逻辑时更轻松地使用 JSON blob/dict,这就是这些约束的原因。)


Jon*_*ice 5

你需要某种Union类型的类型.

from typing import Dict, List, Union

# simple str values
hour_dict: Dict[str, str] = {"test_key": "test_value"}

# more complex values
hour_dict1: Dict[str, Union[str, List[str]]] = {
    "test_key": "test_value", 
    "test_keywords": ["test_1","test_2"]
}
Run Code Online (Sandbox Code Playgroud)

一般来说,当你需要"这个或那个"时,你需要一个Union.在这种情况下,您的选项是strList[str].

有几种方法可以解决这个问题.例如,您可能希望定义类型名称以简化内联类型.

OneOrManyStrings = Union[str, List[str]]

hour_dict2: Dict[str, OneOrManyStrings] = {
    "test_key": "test_value", 
    "test_keywords": ["test_1","test_2"]
}
Run Code Online (Sandbox Code Playgroud)

即使只有一个项目,我也可能会建议简单性,并行性和规律性使所有dict值都变得纯净List[str].这将允许您始终使用len()值,而无需事先进行类型检查或保护条件.但这些点是尼特和调整.