Python mypy 无法从联合 return 类型推断类型
Python mypy unable to infer type from union return types
这里是示例代码
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 也无法推断出它。
Even though one of the dictionary values is int, mypy is unable to infer that.
Mypy 是正确的。你的代码有一个错误,mypy 正确地标记了它。您的代码无法保证 data['start']
和 data['end']
始终为整数。
您的 data
签名是 Dict[str, Union[str, int]]
,因此值的类型是 Union[str, int]
。 Mypy必须假设传入{'start': '2018-07-12', 'end': -42}
总是正确的,所以return值必须是Tuple[Union[str, int], Union[str, int]]
.您声称函数 returns 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]) 是工作的结果
这里是示例代码
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 也无法推断出它。
Even though one of the dictionary values is int, mypy is unable to infer that.
Mypy 是正确的。你的代码有一个错误,mypy 正确地标记了它。您的代码无法保证 data['start']
和 data['end']
始终为整数。
您的 data
签名是 Dict[str, Union[str, int]]
,因此值的类型是 Union[str, int]
。 Mypy必须假设传入{'start': '2018-07-12', 'end': -42}
总是正确的,所以return值必须是Tuple[Union[str, int], Union[str, int]]
.您声称函数 returns 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]) 是工作的结果