I am using Python 3.8.1 and mypy 0.782. I don't understand why mypy complains about the following code:
from typing import Union, List, Dict
Mytype = Union[Dict[str, str], Dict[str, List[str]]]
s: Mytype = {"x": "y", "a": ["b"]}
Mypy gives the following error on line 3:
Incompatible types in assignment (expression has type "Dict[str, Sequence[str]]", variable has type "Union[Dict[str, str], Dict[str, List[str]]]")
If I change the last line to s: Mytype = {"a": ["b"]}
mypy doesn't complain. However, when adding yet one more line s["a"].append("c")
leads to an error:
error: Item "str" of "Union[str, List[str]]" has no attribute "append"
How can the above mentioned be explained? How should I type a dict that has strings as keys and the values can be either strings or lists of strings?
Found this: https://github.com/python/mypy/issues/2984#issuecomment-285716826 but still not completely sure why the above mentioned happens and how should I fix it.
EDIT:
Although it's still not clear why the suggested modification Mytype = Dict[str, Union[str, List[str]]]
does not resolve the error with s['a'].append('c')
I think the TypeDict approach suggested in the comments as well as in https://stackoverflow.com/a/62862029/692695 is the way to go, so marking that approach as a solution.
See similar question at: Indicating multiple value in a Dict[] for type hints, suggested in the comments by Georgy.
Second, a dictionary key must be of a type that is immutable. For example, you can use an integer, float, string, or Boolean as a dictionary key.
Dictionary values can be just about anything (int, lists, functions, strings, etc). For example, the dictionary below, genderDict has ints as keys and strings as values.
It definitely can have a list and any object as value but the dictionary cannot have a list as key because the list is mutable data structure and keys cannot be mutable else of what use are they.
dict is "easier to read" than {} and the meaning is clearer... especially for those who use multiple languages and find it difficult to remember whether it's braces, brackets, curly braces...
Because s: Mytype
cannot have type Dict[str, str]
and type Dict[str, List[str]]
at the same time. You could do what you want like this:
Mytype = Dict[str, Union[str, List[str]]]
But maybe problems, because Dict
is invariant
Also you could use TypedDict
, but only a fixed set of string keys is expected:
from typing import List, TypedDict
MyType = TypedDict('MyType', {'x': str, 'a': List[str]})
s: MyType = {"x": "y", "a": ["b"]}
s['a'].append('c')
NOTE:
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
And, of course, you can use Any
:
Mytype = Dict[str, Any]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With