【问题标题】:mypy, type hint: Union[float, int] -> is there a Number type?mypy,输入提示:Union[float, int] -> 有数字类型吗?
【发布时间】:2018-06-19 12:33:56
【问题描述】:

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

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

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

【问题讨论】:

    标签: python type-hinting mypy python-typing union-types


    【解决方案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
    

    【讨论】:

    【解决方案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
    

    【讨论】:

      猜你喜欢
      • 2018-11-28
      • 2021-11-28
      • 2020-07-21
      • 1970-01-01
      • 2017-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多