mypy 应该从 Union 选项推断类型吗?
在下面的代码中, fn_int
只会以 int
作为参数来调用,但 mypy
抱怨我可能会向它传递一个 str
(fn_str
反之亦然)。
我在这里缺少什么吗? 在将参数传递给 fn_int
和 fn_str
之前,我是否应该/可以以某种方式缩小类型范围?
from typing import Union
def fn_int(arg: int) -> None:
print(arg)
def fn_str(arg: str) -> None:
print(arg)
def fn(arg: Union[str, int]) -> None:
if arg in range(4):
fn_int(arg)
elif arg == "str":
fn_str(arg)
else:
raise ValueError
> mypy mypy_test.py
mypy_test.py:15: error: Argument 1 to "fn_int" has incompatible type "Union[str, int]"; expected "int" [arg-type]
mypy_test.py:17: error: Argument 1 to "fn_str" has incompatible type "Union[str, int]"; expected "str" [arg-type]
In the following code fn_int
will only be called with an int
as an argument, yet mypy
complains I might be passing it a str
(viceversa for fn_str
).
Is there something I'm missing here?
Should/can I somehow narrow down the type before passing arguments to fn_int
and fn_str
?
from typing import Union
def fn_int(arg: int) -> None:
print(arg)
def fn_str(arg: str) -> None:
print(arg)
def fn(arg: Union[str, int]) -> None:
if arg in range(4):
fn_int(arg)
elif arg == "str":
fn_str(arg)
else:
raise ValueError
> mypy mypy_test.py
mypy_test.py:15: error: Argument 1 to "fn_int" has incompatible type "Union[str, int]"; expected "int" [arg-type]
mypy_test.py:17: error: Argument 1 to "fn_str" has incompatible type "Union[str, int]"; expected "str" [arg-type]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您正在寻找的内容称为 类型缩小,而 mypy 没有对
==
或in
比较进行类型缩小。毕竟,它们并不能真正保证类型。作为一个相当常见的示例,在x == 3
或x in range(5)
之后,x 仍然可以是 float 而不是 int。 (当然,标准字符串不会通过in range(4)
检查,标准 int 不会通过== "str"
检查,但你可能有一个奇怪的子类。)mypy 将为以下类型的表达式进行类型缩小:
isinstance(x, SomeClass)
将x
缩小为SomeClass
。issubclass(x, SomeClass)
将x
缩小为Type[SomeClass]
。type(x) is SomeClass
将x
缩小为SomeClass
。callable(x)
将x
缩小为可调用类型。您还可以使用
编写自己的类型保护Typing.TypeGuard
,mypy 也会理解这些。What you're looking for is called type narrowing, and mypy doesn't do type narrowing for
==
orin
comparisons. After all, they don't really guarantee type. As a fairly common example, afterx == 3
orx in range(5)
, x could still be a float rather than an int. (Sure, a standard string won't pass anin range(4)
check, and a standard int won't pass an== "str"
check, but you could have a weird subclass.)mypy will do type narrowing for the following kinds of expressions:
isinstance(x, SomeClass)
narrowsx
toSomeClass
.issubclass(x, SomeClass)
narrowsx
toType[SomeClass]
.type(x) is SomeClass
narrowsx
toSomeClass
.callable(x)
narrowsx
to callable type.You can also write your own type guards with
typing.TypeGuard
, and mypy will understand those too.arg 是 str 或 int,但你从不检查它是什么类型,
因此请检查
if isinstance(arg, int)
。那么 mypy 知道这个函数只有在它是所需类型时才会被调用。
示例:
arg is str or int, but you never check which type it is,
therefore check with
if isinstance(arg, int)
.then mypy knows that this function is only called if it is of desired type.
Example: