问题描述
我输入了一个小函数,但出现了 mypy 错误。我查了一下,发现了一些关于强制转换和添加断言的建议,但它们也无济于事。
我正在使用 mypy==0.812
和 Python 3.6。有关如何解决此问题的任何提示都会有所帮助。
error: Value of type "Optional[Dict[Any,Any]]" is not indexable
这是函数:
from typing import Union
from datetime import datetime
def _get_number(my_dict: Union[dict,None],relevant_key: Union[str,None]) -> int:
if my_dict is None:
return 0
else:
# my_dict: dict = cast(dict,my_dict) # adding this didn't help with the mypy error
# assert isinstance(my_dict,dict) # adding this didn't help with the mypy error
sorted_keys = sorted(
my_dict,key=lambda k: datetime.strptime(my_dict[k],"%H:%M").time(),)
return sorted_keys.index(relevant_key)
解决方法
问题在于,虽然已知 my_dict
是声明 lambda 的字典,但 MyPy 不够聪明,无法知道在调用 lambda 时它仍然是字典。在一般情况下,MyPy 将其标记为错误是正确的:
def test(d: Optional[dict]) -> None:
if d is not None:
# d is definitely a dict where the lambda is declared
f = lambda: print(d['foo'])
d = None
# now d is None when the lambda is called
f()
您的代码与此示例之间的区别在于 my_dict
在声明的 lambda 和被调用之间没有机会变成 None
,因为 sorted
调用了 lambda立即丢弃。但 MyPy 不知道这一点,所以它保守地用相同的错误标记您的代码。
解决方案是使用类型为 dict
的变量而不是 Optional[dict]
。您可以通过在检查 my_actual_dict: dict = my_dict
不是 my_dict
之后声明一个像 None
这样的新变量,然后在 lambda 中使用 my_actual_dict
来实现这一点。由于 my_actual_dict
具有静态类型 dict
,MyPy 知道在 lambda 声明后不能为其分配值 None
。