Mypy:我应该如何键入以字符串作为键且值可以是字符串或字符串列表的字典?

Mypy: How should I type a dict that has strings as keys and the values can be either strings or lists of strings?

我正在使用 Python 3.8.1 和 mypy 0.782。我不明白为什么 mypy 会抱怨以下代码:

from typing import Union, List, Dict
Mytype = Union[Dict[str, str], Dict[str, List[str]]]
s: Mytype = {"x": "y", "a": ["b"]}

Mypy 在第 3 行给出以下错误:

Incompatible types in assignment (expression has type "Dict[str, Sequence[str]]", variable has type "Union[Dict[str, str], Dict[str, List[str]]]")

如果我将最后一行更改为 s: Mytype = {"a": ["b"]} mypy 不会抱怨。但是,当再添加一行时 s["a"].append("c") 会导致错误:

error: Item "str" of "Union[str, List[str]]" has no attribute "append"

上面说的怎么解释呢?我应该如何键入以字符串为键且值可以是字符串或字符串列表的字典?

发现这个:https://github.com/python/mypy/issues/2984#issuecomment-285716826 但仍然不完全确定为什么会发生上述情况以及我应该如何解决它。

编辑: 虽然仍然不清楚为什么建议的修改 Mytype = Dict[str, Union[str, List[str]]] 不能解决 s['a'].append('c') 的错误,但我认为评论和 中建议的 TypeDict 方法是可行的方法,所以将该方法标记为解决方案。

参见类似问题:,由 Georgy 在评论中提出。

因为s: Mytype不能同时有类型Dict[str, str]和类型Dict[str, List[str]]。你可以像这样做你想做的事:

    Mytype = Dict[str, Union[str, List[str]]]

但可能会有问题,因为 Dict 是不变的


更新:

您也可以使用 TypedDict,但只需要一组固定的字符串键:

from typing import List, TypedDict

Mytype = TypedDict('Mytype', {'x': str, 'a': List[str]})
s: Mytype = {"x": "y", "a": ["b"]}

s['a'].append('c')

注意:

Unless you are on Python 3.8 or newer (where TypedDict is available in standard library typing module) you need to install typing_extensions using pip to use TypedDict


当然,您可以使用 Any:

Mytype = Dict[str, Any]