mypy,输入提示:Union[float, int] -> 是不是有 Number 类型?

Posted

技术标签:

【中文标题】mypy,输入提示:Union[float, int] -> 是不是有 Number 类型?【英文标题】:mypy, type hint: Union[float, int] -> is there a Number type?mypy,输入提示:Union[float, int] -> 是否有 Number 类型? 【发布时间】:2018-11-28 10:17:07 【问题描述】:

mypy 真的很方便,可以捕捉很多错误,但是当我编写“科学”应用程序时,我经常会这样做:

def my_func(number: Union[float, int]):
    # Do something

number 是浮点数或整数,取决于用户的输入。有官方的方法吗?

【问题讨论】:

【参考方案1】:

只使用float,因为int 隐含在该类型中:

def my_func(number: float):

PEP 484 Type Hints 特别声明:

与其要求用户编写导入编号然后使用numbers.Float 等,此PEP 提出了一个几乎同样有效的简单快捷方式:当一个参数被注释为具有float 类型时,一个参数为输入int 是可以接受的;类似地,对于注释为复杂类型的参数,float 或 int 类型的参数是可以接受的。

(我的粗体强调)。

理想情况下,您仍会使用numbers.Real

from numbers import Real

def my_func(number: Real):

因为这也将接受 fractions.Fraction()decimal.Decimal() 对象;数字金字塔比整数和浮点值更广泛。

但是,当使用 mypy 进行类型检查时,这些当前不起作用,请参阅 Mypy #3186。

【讨论】:

切向相关,但Decimal 实际上不是Real 的子类,或者根本不是数字塔的一部分:python.org/dev/peps/pep-3141/#the-decimal-type @user1475412 — 有趣的是,decimal.Decimal 现在注册为numbers.Number 的虚拟子类(尽管仍然不是numbers.Real 的虚拟子类)。我认为将其添加为虚拟子类的决定必须是在编写 PEP 后的一段时间内做出的。 github.com/python/cpython/blob/… @AlexWaygood:我认为你误解了什么; decimal.Decimal 早在 PEP 之前就已为 13 years now 注册为 Number。它仍然不是 numbers.Real 的虚拟子类,这正是 user1475412 所说的。 @MartijnPieters,我不确定我是否理解您的观点。您发布的 GitHub 链接显示 decimal.Decimal 已在 2009 年注册为 Number 的子类,但 PEP 3141 是在 2007 年编写的。所以我不确定您如何辩称 decimal.Decimal 已注册为 @987654350 @ 在编写和接受 PEP 之前。 numbers.Number 的第一稿显示该模块只是为了响应 PEP 3141 的接受而创建的:github.com/python/cpython/commit/… 我知道Decimal 不是numbers.Real 的虚拟子类,但user1475412 还说:“Decimal 实际上根本不是 [...] 数字塔的一部分",解释 PEP 3141。我将 PEP 中的那一行解释为 PEP 的作者不打算将Decimal 注册为numbers 类的任何 的虚拟子类在那个时间点。我的解释错了吗?【参考方案2】:

您可以定义自己的类型来解决这个问题并保持代码更简洁。

FloatInt = Union[float, int]

def my_func(number: FloatInt):
    # Do something

【讨论】:

好主意,但是当float 存在时,int 正式多余。看到这个答案:***.com/a/50928627/4960855【参考方案3】:

Python > 3.10 允许您执行以下操作。

def my_func(number: int | float) -> int | float: 

【讨论】:

正如 Martijn 的回答所指出的,mypy 文档明确指出“当参数被注释为浮点类型时,int 类型的参数是可以接受的”。在这里显式注释联合是没有意义的。 @AlexWaygood 虽然这种说法在大多数情况下都是正确的,但说类型联合通常毫无意义是错误的。 intfloat 通常是不同的东西,如果您的代码需要在本地区分这些差异,则类型联合是合适的。看例如在dir(1)dir(1.0)。如果您需要在其中任何一个上定义的任何成员函数,则需要类型联合,以便代码正确进行类型检查。 @bluenote10 感谢您的更正;你说得对,我的评论措辞太强了。【参考方案4】:

对于没有共同超类型的实体(例如Union[int, numpy.ndarray])的更一般问题的联合类型提示问题,解决方案是从typing 导入Union .

示例 1:

from typing import Union

def my_func(number: Union[float, int]):
    # Do something

示例 2:

from typing import Union
import numpy as np

def my_func(x: Union[float, np.ndarray]):
    # do something
    # Do something

【讨论】:

以上是关于mypy,输入提示:Union[float, int] -> 是不是有 Number 类型?的主要内容,如果未能解决你的问题,请参考以下文章

mypy 错误 - 尽管使用了“Union”,但类型不兼容

使用 Mypy 本地存根

mypy:如何最好地处理 random.choice

将类型指定为数字列表(整数和/或浮点数)?

将值列表映射到浮点数时出现mypy错误

如何定义重载类型签名?