The currently accepted solution of using Number
is fairly broken considering that, as pointed out in the comments, int
s are not Number
s for static type checkers like mypy and PyRight. The situation has been discussed for years with no clear resolution.
Another possible approach extracted from a detailed explanation from a related question is:
from typing import SupportsFloat as Numeric
which has the following behavior:
from decimal import Decimal
from fractions import Fraction
from typing import SupportsFloat as Numeric
import numpy as np
def f(x: Numeric) -> None:
pass
# Accepted by mypy/Pyright:
f(123)
f(np.uintc(55))
f(Fraction(-3, 2))
f(Decimal("-3.14"))
f(np.array([1, 2, 3])) # Should an array be numeric?
# Results in type errors:
f(complex(2, 3))
f("asdf")
This has the advantage of being fairly permissive, except for complex
. In case you want to include complex
as well, simply do
from typing import SupportsFloat, Union
Numeric = Union[SupportsFloat, complex]
or equivalently in Python ≥3.10 style:
from typing import SupportsFloat, TypeAlias
Numeric: TypeAlias = SupportsFloat | complex
It's perhaps unfortunate that NumPy arrays are considered numeric in the sense of SupportsFloat
, but that illustrates the obscure philosophical nature of the question "what is a number?".
Major disadvantage:
As noted by @lkwbr, the SupportsFloat
type is only really suitable for identifying numbers. It fails to support any operators like addition or comparison.
For instance, Pyright gives the following error:
Operator "<" not supported for types "SupportsFloat" and "SupportsFloat"