mypy声明了不兼容的类型,尽管所有类型都是显式的并使用Union


from enum import Enum
class MyEnum(Enum):
FIRST = 1, 'first'
SECOND = 2 , 'second'
__myenum_int_ref: Dict[int, MyEnum] = {k.value[0]: k for k in MyEnum}
__myenum_str_ref: Dict[str, MyEnum] = {k.value[1]: k for k in MyEnum}
__myenum_str_ref.update({k.name: k for k in MyEnum})
__flags_ref: Dict[Union[Type[str], Type[int]], Dict[Union[str, int], MyEnum]] = {
str: __myenum_str_ref,
int: __myenum_int_ref,
}

当我运行mypy时,我得到这个错误

function.py:14: error: Dict entry 0 has incompatible type "Type[str]": "Dict[str, MyEnum]"; expected "Union[Type[str], Type[int]]": "Dict[Union[str, int], MyEnum]"
function.py:15: error: Dict entry 1 has incompatible type "Type[int]": "Dict[int, MyEnum]"; expected "Union[Type[str], Type[int]]": "Dict[Union[str, int], MyEnum]"

我已经明确地描述了键可以是int类型和str类型,我在字典中插入了int类型和str类型的键。

我知道这是正确的,因为在python 3.10上,使用Type[int|str]是首选方式,mypy确实完全接受它,而且它是"糖语法";添加,这样您就不必编写Union[Type[int], Type[str]]。但我需要使用python 3.9,并且我一直坚持对类型使用Union,mypy抱怨即使在处理显式类型时它也不兼容。

因为您的值类型是Dict[str, MyEnum]Dict[int, MyEnum],所以应该使用Union[Dict[str, MyEnum], Dict[int, MyEnum]]而不是Dict[Union[str, int], MyEnum]:

Dict[Union[Type[str], Type[int]], Union[Dict[str, MyEnum], Dict[int, MyEnum]]]
# in Python3.9
dict[Union[type[str], type[int]], Union[dict[str, MyEnum], dict[int, MyEnum]]]
# in Python3.10+
dict[type[str] | type[int], dict[str, MyEnum] | dict[int, MyEnum]]

更新:

使用Protocol,您可以通过mypy检查:

from typing import Protocol, TypeVar
_T = TypeVar('_T')

class FlagsRef(Protocol[_T]):
def __getitem__(self, item: type[_T]) -> dict[_T, MyEnum]: ...

__flags_ref: FlagsRef = {   # pass
str: __myenum_str_ref,
int: __myenum_int_ref,
}
int_ref: dict[int, MyEnum] = __flags_ref[int]   # pass

最新更新