mypy 错误:错误:“Optional[Dict[Any, Any]]”类型的值不可索引

问题描述

我输入了一个函数,但出现了 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