目前被广泛接受的使用 Number
的解决方案存在严重问题,因为如评论中所指出的那样,对于像 mypy 和 PyRight 这样的静态类型检查器来说,int
不是 Number
。这个情况已经讨论了多年,但没有明确的解决方案。
另一个可能的方法是从相关问题的详细解释中提取的:
from typing import SupportsFloat as Numeric
具有以下行为:
from decimal import Decimal
from fractions import Fraction
from typing import SupportsFloat as Numeric
import numpy as np
def f(x: Numeric) -> None:
pass
f(123)
f(np.uintc(55))
f(Fraction(-3, 2))
f(Decimal("-3.14"))
f(np.array([1, 2, 3]))
f(complex(2, 3))
f("asdf")
这种做法相当宽容,除了complex
。如果您想要包含complex
,只需要执行以下操作即可。
from typing import SupportsFloat, Union
Numeric = Union[SupportsFloat, complex]
或者在Python ≥3.10风格中等效地表示:
from typing import SupportsFloat, TypeAlias
Numeric: TypeAlias = SupportsFloat | complex
或许有些不幸的是,NumPy数组在"SupportsFloat"的意义上被认为是数字,但这也体现了问题“什么是数字?”的深奥哲学性。
主要缺点:
正如@lkwbr所指出的那样,“SupportsFloat”类型只适用于识别数字,它无法支持任何像加法或比较之类的运算符。
例如,Pyright会给出以下错误:
运算符"<"不支持类型 "SupportsFloat" 和 "SupportsFloat"
isinstance(0+1j, Number)
的结果为“True”。 - Walter Trossfoo(1)
时,mypy会抱怨foo
的类型不兼容,期望的是“Number”类型而不是“int”类型。换句话说,这个答案对于使用mypy的用户来说无法工作。请参阅此mypy问题。 - normaniusfoo(np.int32(1))
也是同样的情况。mypy会产生类似的错误提示:Argument 1 to "foo" has incompatible type "floating[_32Bit]"; expected "Number"
。你有什么建议适用于mypy用户吗? - normanius