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 虽然这种说法在大多数情况下都是正确的,但说类型联合通常毫无意义是错误的。int
和 float
通常是不同的东西,如果您的代码需要在本地区分这些差异,则类型联合是合适的。看例如在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 类型?的主要内容,如果未能解决你的问题,请参考以下文章