我在python上有以下字典:
dictionary = {'key1': 1,
'sub_dict': {'key2': 0}
}
当我在以下行上运行mypy时:
print(dictionary['sub_dict']['key2'])
它引起错误Value of type "object" is not indexable
答案 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']
本身再也不能拥有其他任何键了大于int
和dictionary
。 (在这个假设的世界中,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},
}