Consider the following code:
#!/usr/bin/env python3
import time
from typing import Dict, Union, Any, cast, Callable
some_variable = {'aaa': '123', 'zzz': 1} # type: Dict[str, Union[str, int]]
# ensure that some_variable['zzz'] is an int
some_variable['zzz'] = int(some_variable['zzz'])
sleep_time = some_variable['zzz'] # type: int
time.sleep(sleep_time)
Clearly, by the time sleep_time
is defined, the type of some_variable['zzz']
is an int
.
Yet, mypy gives an error: Incompatible types in assignment (expression has type "Union[str, int]", variable has type "int")
.
My questions is: how to tell mypy that the type is int
at that point in the code? And better: how to tell mypy that the type is some complex data structure at that point in the code?
Notes:
As far as I know, there is no way to tell mypy about the data structure for a specific key in
dict
during initialization of the dict, so I like to tell mypy about the structure when I process it. That's what I try to do withsleep_time = some_variable['zzz'] # type: int
.assert isinstance(some_variable['zzz'], int)
does suppress the error. Unfortunately, I can't useisinstance
, since the actual data type in my code is not an int, but more complex data structure. Adding a linesome_variable['zzz'] = cast(int, some_variable['zzz'])
orsome_variable['zzz'] = int(some_variable['zzz'])
does not seem to make a difference to mypy. That's too bad, as cast() can take complex data structures, and I can define a complex data structure as the output of a type coercion function.To my surprise,
some_variable = {'aaa': '123', 'zzz': 1} # type: Dict[str, Any]
(thus withAny
instead ofUnion[str,int]
) silences any errors by mypy.Adding
type: int
to the linesome_variable['zzz'] = int(some_variable['zzz'])
gives an error:Unexpected type declaration
.FYI, my actual codes is more akin to the following, where
some_variable
is read from file, but with more complex normalisation functions thanstr.lower()
andint()
.
mappers = {
'aaa': str.lower,
'zzz': int
} # type: Dict[str, Callable[[Any], Union[str, int]]]
defaults = {
'aaa': '',
'zzz': 2
} # type: Dict[str, Union[str, int]]
for key, value in some_variable.items():
try:
some_variable[key] = mappers[key](value)
except Exception:
some_variable[key] = defaults[key]