如何在 Python 中键入提示通用数字类型?

Fra*_*Boi 23 python types type-hinting python-3.x

如果之前有人问过这个问题,但我找不到任何相关的答案,请原谅我。

考虑一个将数字类型作为输入参数的函数:

def foo(a):
    return ((a+1)*2)**4;
Run Code Online (Sandbox Code Playgroud)

这适用于整数、浮点数和复数。

是否有基本类型,以便我可以进行类型提示(真实现有类型/基类),例如:

def foo(a: numeric):
    return ((a+1)*2)**4;
Run Code Online (Sandbox Code Playgroud)

此外,我需要在集合类型参数中使用它,例如:

from typing import Collection;
def foo(_in: Collection[numeric]):
    return ((_in[0]+_in[1])*2)**4;
Run Code Online (Sandbox Code Playgroud)

jua*_*aga 29

PEP 3141添加了数字的抽象基类,因此您可以使用:

from numbers import Number

def foo(a: Number) -> Number:
    ...
Run Code Online (Sandbox Code Playgroud)

  • 当我调用 `foo(1)` 时,mypy 抱怨 `foo 有不兼容的类型“int”;预期“数字”`。换句话说:这个答案不适用于 mypy 用户。另请参阅此开放的 [mypy 问题](https://github.com/python/mypy/issues/3186)。 (11认同)
  • 请小心,因为“Number”包含“Complex”:“isinstance(0+1j, Number)”为“True” (2认同)
  • 顺便说一下,“foo(np.int32(1))”的情况也是如此。mypy 引发类似的错误:`“foo”的参数 1 具有不兼容的类型“floating[_32Bit]”;预期“数字”`。mypy 用户应该做什么有什么建议吗? (2认同)

blh*_*ing 10

typing模块中没有通用数字类型,因此您必须使用以下方法创建这样的类型Union

from typing import Union

numeric = Union[int, float, complex]

...
Run Code Online (Sandbox Code Playgroud)

要添加对 Numpy 的数字类型集合的支持,请添加np.number到该 Union 中。

numeric = Union[int, float, complex, np.number]
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这不适用于 numpy dtypes,但接受的答案适用。 (2认同)
  • @sturgemeister我有点困惑,因为`foo(np.float32(42))`会导致mypy(我正在使用的静态类型检查器)发出`参数1到“foo”具有不兼容的类型“floating[_32Bit” ]”;预期“数字”`。您使用什么类型检查器验证您的声明? (2认同)

Ben*_*res 6

当前接受的 using 解决方案Number相当糟糕,因为正如评论中指出的那样,ints 不适Number用于 mypy 和 PyRight 等静态类型检查器。这种情况已经讨论了多年,但没有明确的解决方案

\n

从相关问题的详细解释中提取的另一种可能的方法是:

\n
from typing import SupportsFloat as Numeric\n
Run Code Online (Sandbox Code Playgroud)\n

其具有以下行为:

\n
from decimal import Decimal\nfrom fractions import Fraction\nfrom typing import SupportsFloat as Numeric\n\nimport numpy as np\n\n\ndef f(x: Numeric) -> None:\n    pass\n\n\n# Accepted by mypy/Pyright:\nf(123)\nf(np.uintc(55))\nf(Fraction(-3, 2))\nf(Decimal("-3.14"))\nf(np.array([1, 2, 3]))  # Should an array be numeric?\n\n# Results in type errors:\nf(complex(2, 3))\nf("asdf")\n
Run Code Online (Sandbox Code Playgroud)\n

这样做的优点是相当宽松,但complex. 如果您complex也想包括在内,只需执行以下操作即可

\n
from typing import SupportsFloat, Union\n\nNumeric = Union[SupportsFloat, complex]\n
Run Code Online (Sandbox Code Playgroud)\n

或等效于 Python \xe2\x89\xa53.10 风格:

\n
from typing import SupportsFloat, TypeAlias\n\nNumeric: TypeAlias = SupportsFloat | complex\n
Run Code Online (Sandbox Code Playgroud)\n

也许不幸的是,NumPy 数组在 的意义上被认为是数字SupportsFloat,但这说明了“什么是数字?”这个问题的晦涩的哲学本质。

\n

主要缺点:

\n

正如@lkwbr 所指出的,该SupportsFloat类型仅真正适合识别数字。它不支持任何运算符,例如加法或比较。

\n

例如,Pyright 给出以下错误:

\n
\n

类型“SupportsFloat”和“SupportsFloat”不支持运算符“<”

\n
\n