这是示例代码
from typing import Dict, Union, Tuple
def select_range(data: Dict[str, Union[str, int]]) -> Tuple[int, int]:
if data['start'] and data['end']:
return data['start'], data['end']
return 1, 1
select_range({})
Mypy 输出:
mypy different_return.py
different_return.py:6: error: Incompatible return value type (got
"Tuple[Union[str, int], Union[str, int]]", expected "Tuple[int, int]")
即使字典值之一是
int
,mypy 也无法推断出这一点。
即使字典值之一是 int,mypy 也无法推断出这一点。
Mypy 是正确的。您的代码有一个错误,并且 mypy 正确地标记了它。您的代码中不能保证
data['start']
和 data['end']
始终是整数。
您的
data
签名是 Dict[str, Union[str, int]]
,因此值的类型为 Union[str, int]
。 Mypy must 假设传入 {'start': '2018-07-12', 'end': -42}
始终是正确的,因此返回值 must 为 Tuple[Union[str, int], Union[str, int]]
。您声称该函数返回 Tuple[int, int]
与此相冲突。
运行时“实际”发生什么并不重要。这不是重点; mypy 是一个静态类型检查器,旨在帮助您保持运行时行为无错误。这里重要的是,根据类型提示,可能为 start
和
end
传递非整数值,因此类型检查器无法保护您免受代码中意外设置的未来错误的影响这两个键中任意一个的字符串值。如果你在字典中传递结构化数据,你将总是不得不为此与 mypy 作斗争,因为字典实际上是错误的结构。您确实想在此处使用命名元组或数据类
FooBar
,但对于您的特定应用程序,我确信您传递的数据结构会有一个更好的名称:
from typing import NamedTuple
class FooBar(NamedTuple):
start: int
end: int
# other fields, perhaps with defaults and Optionals
def select_range(data: FooBar) -> Tuple[int, int]:
if data.start and data.end:
return data.start, data.end
return 1, 1
from typing import Dict, Union, Tuple
def select_range(data: Dict[str, Union[str, int]]) -> Tuple[int, int]:
print (data)
if data['start'] and data['end']:
return data['start'], data['end']
return 1, 1
print (select_range({"start":[1,5], 'end':[2,6]}))
用它来查找一些参数:
from typing import Dict, Union, Tuple
def select_range(data: Dict[str, Union[str, int]]) -> Tuple[int, int]:
# print (data)
if 'start' in data and 'end' in data:
return data['start'], data['end']
return 1, 1
print (select_range({"start":[5], 'end':[6]}))
#select_range({})
([5], [6]) 是工作的结果