字典的字典发生Mypy错误:“对象”类型的值不可索引

时间:2019-02-20 12:37:55

标签: python dictionary mypy

我在python上有以下字典:

dictionary = {'key1': 1,
              'sub_dict': {'key2': 0}
             }

当我在以下行上运行mypy时:

print(dictionary['sub_dict']['key2'])

它引起错误Value of type "object" is not indexable

2 个答案:

答案 0 :(得分:2)

静态键入非常棘手。 mypy可以确定dictionary的值不是全部具有相同的类型,但是就其种类而言。基于初始值,dictionary static 类型为Dict[str,object]。但是,mypy不会尝试进一步模拟代码,这意味着d['sub_dict']在您所处的位置还静止另一个dict时不知道尝试使用key2对其进行索引,这会导致类型错误。

您可以做的一件事是帮助mypy,方法是使用typing.cast告诉它可以将特定值视为具有特定类型。

print(typing.cast(typing.Dict[str,dict], d['sub_dict'])['key2'])

在运行时,typing.cast实际上是一个标识函数;它只是返回第二个参数。 mypy将其视为更强的类型提示,表示无论之前是否有任何提示或注释,d['sub_dict']都应视为Dict[str,dict]

不过请注意,通过使用cast,您是在告诉mypy 承担确保dictionary['sub_dict']实际上是dict在运行时,因为这不是静态类型可以传达的东西。您可能会认为

dictionary : Dict[str,Union[int,dict]] = ...

可以工作,但这只是告诉mypy,因为dictionary['foo'] = 'bar'既不是'bar'也不是{{1} }。即使有了更准确的类型提示,int仍然无法知道dict的哪种类型的值将任何特定的键映射到了。

您也可以使用mypy

dictionary

因为现在您说的是可以将任何类型用作值,并且可以将任何类型用作索引结果,并且这两种类型不必对齐。也就是说,Any很好,因为dictionary: Dict[str,Any] = ... dictionary['key1'] = 3兼容,但是int也很好,因为Any产生的东西也是 dictionary['sub_dict']['key2']兼容,并且您可以假定该类型本身是可索引的。实际上,它涵盖了在代码中任何地方dictionary['sub_dict']任何用法,而不是您使用Any来确定应允许的内容的特定位置。


主要离题:有一个依赖类型的概念,最简单的例子是类似dictionary的类型,它与cast相同,只是它没有允许为负值。 PositiveInt似乎具有类似的从属类型,其中值的类型实际上是存储在值中的实际数据的函数。例如,假设您可以将int instance dictionary一起使用以指定其值的类型。

dict

现在,Dict不仅可以说dictionary: Dict[str, {"key1": int, "sub_dict": dict}] = {'key1': 1, 'sub_dict': {'key2': 0} } 应该是mypy,而且dictionary['key1']本身再也不能拥有其他任何键了大于intdictionary。 (在这个假设的世界中,key1可以将任意未指定的键映射到默认类型。)

答案 1 :(得分:1)

一个对我有用的简单改变就是这个。

from typing import Any, Dict

dictionary: Dict[str, Any] = {
    'key1': 1,
    'sub_dict': {'key2': 0},
}

这告诉 mypy 你的字典的值可以是任何类型。如果您的值多种多样(整数、浮点数、字符串、字典等),那么最好使用 Any 类型注释。

特别是对于 OP 的字典,以下可能更合适。

from typing import Tuple, Dict

dictionary: Dict[str, Tuple[int, Dict]] = {
    'key1': 1,
    'sub_dict': {'key2': 0},
}