【发布时间】:2018-11-28 10:17:07
【问题描述】:
mypy 真的很方便,可以捕捉很多错误,但是当我编写“科学”应用程序时,我经常会这样做:
def my_func(number: Union[float, int]):
# Do something
number 是浮点数或整数,取决于用户的输入。有官方的方法吗?
【问题讨论】:
标签: python type-hinting mypy python-typing union-types
mypy 真的很方便,可以捕捉很多错误,但是当我编写“科学”应用程序时,我经常会这样做:
def my_func(number: Union[float, int]):
# Do something
number 是浮点数或整数,取决于用户的输入。有官方的方法吗?
【问题讨论】:
标签: python type-hinting mypy python-typing union-types
只使用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
decimal.Decimal 现在注册为numbers.Number 的虚拟子类(尽管仍然不是numbers.Real 的虚拟子类)。我认为将其添加为虚拟子类的决定必须是在编写 PEP 后的一段时间内做出的。 github.com/python/cpython/blob/…
decimal.Decimal 早在 PEP 之前就已为 13 years now 注册为 Number。它仍然不是 numbers.Real 的虚拟子类,这正是 user1475412 所说的。
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 类的任何 的虚拟子类在那个时间点。我的解释错了吗?
您可以定义自己的类型来解决这个问题并保持代码更简洁。
FloatInt = Union[float, int]
def my_func(number: FloatInt):
# Do something
【讨论】:
float 存在时,int 正式多余。看到这个答案:stackoverflow.com/a/50928627/4960855
Python > 3.10 允许您执行以下操作。
def my_func(number: int | float) -> int | float:
【讨论】:
int 和 float 通常是不同的东西,如果您的代码需要在本地区分这些差异,则类型联合是合适的。看例如在dir(1) 与dir(1.0)。如果您需要在其中任何一个上定义的任何成员函数,则需要类型联合,以便代码正确进行类型检查。
对于没有共同超类型的实体(例如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
【讨论】: