Python mypy 无法从联合返回类型推断类型

问题描述 投票:0回答:2

这是示例代码

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 也无法推断出这一点。

python mypy python-typing
2个回答
6
投票

即使字典值之一是 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



-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]) 是工作的结果

© www.soinside.com 2019 - 2024. All rights reserved.