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

时间:2017-12-28 19:53:58

标签: python python-3.x static-typing mypy

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

real_hour: int = lower_hour + hour_iterator

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

from typing import Dict, List
hour_dict: Dict[str, str] = {"test_key": "test_value"}

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

hour_dict = {"test_key": "test_value", "test_keywords": ["test_1","test_2"]}

如果我不为这些词典使用静态类型 - mypy会向我显示错误,例如:

len(hour_dict['test_keywords'])
- Argument 1 to "len" has incompatible type

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

2 个答案:

答案 0 :(得分:5)

您需要某种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"] } 类型。

Union

通常,当您需要“这个或那个”时,您需要str。在这种情况下,您的选项为List[str]OneOrManyStrings = Union[str, List[str]] hour_dict2: Dict[str, OneOrManyStrings] = { "test_key": "test_value", "test_keywords": ["test_1","test_2"] }

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

dict

即使只有一个项目,我也可以建议简单性,并行性和规律性使所有List[str]值纯len()。这样您就可以始终获取值的{{1}},而无需事先进行类型检查或保护条件。但这些点是尼特和调整。

答案 1 :(得分:1)

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

要使用此类型,必须先使用pip安装mypy_extensions第三方库。然后,您可以执行以下操作:

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"]
}

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

hour_dict = MyDictType(
    test_key="test_value", 
    test_keywords=["test_1","test_2"]
)

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

  1. 仅当dict包含具有在编译时都已知的类型的特定键时才有用 - 如果您期望真正动态的dict,则应使用常规Dict[...]
  2. 键必须都是字符串。
  3. 目前,这种类型只有mypy才能理解(虽然我知道有一些计划最终会将TypedDict添加到PEP 484,一旦它经过多次战斗测试,这意味着任何符合PEP 484标准的类型检查器都会需要支持它。)
  4. TypedDict旨在使编写序列化/反序列化逻辑时更容易使用JSON blob / dicts,这就是这些约束的原因。)