首页 > 解决方案 > dict的dict上的Mypy错误:“object”类型的值不可索引

问题描述

我在 python 上有以下字典:

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

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

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

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

标签: pythondictionarymypy

解决方案


静态类型很棘手。mypy可以确定 的值dictionary并非都具有相同的类型,但仅此而已。的静态类型dictionaryDict[str,object],基于初始值。但是,mypy不会尝试进一步模拟代码,这意味着它不知道在您尝试使用 索引它时d['sub_dict']是否仍然是另一个,这会导致类型错误。dictkey2

您可以做的一件事是mypy通过告诉它可以将特定值视为具有特定类型来提供帮助,使用typing.cast.

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

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

但是请注意,通过使用,cast您是在告诉要负责确保它实际上是在运行时 a ,因为这不是您可以用静态类型传达的东西。你可能会认为像mypydictionary['sub_dict']dict

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

会起作用,但这只是说明mypywrite 将是类型错误dictionary['foo'] = 'bar',因为'bar'既不是 an 也不是inta dict。即使有更准确的类型提示,仍然无法mypy知道dictionary将任何特定键映射到哪种类型的值。

你也可以使用Any

dictionary: Dict[str,Any] = ...

因为现在你说任何类型都可以作为值,任何类型都可以假定为索引的结果,这两种类型不必排成一行。也就是说,dictionary['key1'] = 3很好,因为int与 兼容Any,但dictionary['sub_dict']['key2']也很好,因为dictionary['sub_dict']产生的任何东西与 兼容Any,并且您可以假设该类型本身是可索引的。实际上,它涵盖了代码中任何地方的任何使用,而不是您用来断言应该允许什么dictionary的特定位置。cast


主要题外话:有一个依赖类型的概念,最简单的例子是一个类似的类型,除了它不允许负值外,它PositiveInt是相同的。似乎具有类似的依赖类型,其中值的类型实际上是存储在值中的实际数据的函数。例如,假设您可以使用with的实例来指定其值的类型。intdictionarydictDict

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

现在,不仅可以mypy看出它dictionary['key1']应该是一个int,而且它dictionary本身永远不能有除and之外的任何键。(在这个假设的世界中, a可以将任意未指定的键映射到默认类型。)key1sub_dictdefaultdict


推荐阅读