dict dict上的Mypy错误:“object”类型的值不可索引

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

我在python上有以下字典:

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

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

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

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

python dictionary mypy
1个回答
2
投票

静态打字很棘手。 mypy可以确定dictionary的值并不都具有相同的类型,但这就是它的范围。 dictionary的静态类型是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]] = ...

会工作,但这只是告诉mypydictionary['foo'] = 'bar'将是一个类型错误,因为'bar'既不是int也不是dict。即使有更准确的类型提示,mypy仍然无法知道dictionary将任何特定键映射到什么类型的值。

你也可以使用Any

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

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


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

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

现在,mypy不仅可以说dictionary['key1']应该是int,而且dictionary本身除了key1sub_dict之外永远不会有任何关键。 (在这个假设的世界中,defaultdict可以将任意未指定的键映射到默认类型。)

© www.soinside.com 2019 - 2024. All rights reserved.