How to type hint a generic numeric type in Python?

The currently accepted solution of using Number is fairly broken considering that, as pointed out in the comments, ints are not Numbers 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?".


PEP 3141 added abstract base classes for numbers, so you could use:

from numbers import Number

def foo(a: Number) -> Number:
    ...

There isn't a generic numeric type in the typing module, so you would have to create such a type with Union instead:

from typing import Union

numeric = Union[int, float, complex]

...

To add support for Numpy's collection of numeric types, add np.number to that Union.

numeric = Union[int, float, complex, np.number]