mypy 应该从 Union 选项推断类型吗?

发布于 2025-01-13 09:37:24 字数 902 浏览 0 评论 0原文

在下面的代码中, fn_int 只会以 int 作为参数来调用,但 mypy 抱怨我可能会向它传递一个 strfn_str 反之亦然)。

我在这里缺少什么吗? 在将参数传递给 fn_intfn_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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

陈甜 2025-01-20 09:37:24

您正在寻找的内容称为 类型缩小,而 mypy 没有对 ==in 比较进行类型缩小。毕竟,它们并不能真正保证类型。作为一个相当常见的示例,在 x == 3x 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 SomeClassx 缩小为 SomeClass
  • callable(x)x 缩小为可调用类型。

您还可以使用 编写自己的类型保护Typing.TypeGuard,mypy 也会理解这些。

What you're looking for is called type narrowing, and mypy doesn't do type narrowing for == or in comparisons. After all, they don't really guarantee type. As a fairly common example, after x == 3 or x in range(5), x could still be a float rather than an int. (Sure, a standard string won't pass an in 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) narrows x to SomeClass.
  • issubclass(x, SomeClass) narrows x to Type[SomeClass].
  • type(x) is SomeClass narrows x to SomeClass.
  • callable(x) narrows x to callable type.

You can also write your own type guards with typing.TypeGuard, and mypy will understand those too.

dawn曙光 2025-01-20 09:37:24

arg 是 str 或 int,但你从不检查它是什么类型,
因此请检查if isinstance(arg, int)

那么 mypy 知道这个函数只有在它是所需类型时才会被调用。

示例

if isinstance(arg, int):
    fn_int(arg)
elif isinstance(arg, str):
    fn_str(arg)
else:
    raise ValueError

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:

if isinstance(arg, int):
    fn_int(arg)
elif isinstance(arg, str):
    fn_str(arg)
else:
    raise ValueError
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文