Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

125
Views
How to hint at number *types* (i.e. subclasses of Number) - not numbers themselves?

Assuming I want to write a function that accepts any type of number in Python, I can annotate it as follows:

from numbers import Number

def foo(bar: Number):
    print(bar)

Taking this concept one step further, I am writing functions which accept number types, i.e. int, float or numpy dtypes, as arguments. Currently, I am writing:

from typing import Type

def foo(bar: Type):
    assert issubclass(bar, Number)
    print(bar)

I thought I could substitute Type with something like NumberType (similar to NotImplementedType and friends, re-introduced in Python 3.10), because all number types are subclasses of Number:

from numbers import Number
import numpy as np

assert issubclass(int, Number)
assert issubclass(np.uint8, Number)

As it turns out (or at least as far as I can tell), there is no such thing as a generic NumberType in Python (3.9):

>>> type(Number)
abc.ABCMeta

Is there a clean way (i.e. without runtime checks) to achieve the desired kind of annotation?

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

There is no general way to do this. Numbers are not strictly related to begin with and their types are even less.


While numbers.Number might seem like "the type of numbers" it is not universal. For example, decimal.Decimal is explicitly not a numbers.Number as either subclass, subtype or virtual subclass. Specifically for typing, numbers.Number is not endorsed by PEP 484 -- Type Hints.

In order to meaningfully type hint "numbers", one has to explicitly define what numbers are in that context. This might be a pre-existing numeric type set such as int <: float <: complex, a typing.Union/TypeVar of numeric types, a typing.Protocol to define operations and algebraic structure, or similar.

from typing import TypeVar
from decimal import Decimal
from fractions import Fraction

#: typevar of rational numbers if we squint real hard
Q = TypeVar("Q", float, Decimal, Fraction)

All that said, "the type of the type of numbers" is even less meaningful. Even the specific numbers.Number has practically no features at all: it cannot be converted to a concrete type, nor can it be instantiated to a meaningful number.

Instead, use "the type of some type of numbers":

from typing import Type

def zero(t: Type[Q]) -> Q:
    return t()  # all Type[Q]s can be instantiated without arguments

print(zero(Fraction))

If the only goal of the Type is to create instances, it can be better to request a Callable instead. This covers types as well as factory functions.

def one(t: Callable[[int], Q]) -> Q:
    return t(1)
over 4 years ago · Santiago Trujillo Report

0

This is not quite an answer to the original question. (Alex Waygood's answer is properly selected as responsive.) However, I have attempted to generalize my own work-arounds for the sharp edges between numbers and typing in Python. Those work-arounds now live in numerary (having extracted it via c-section from dyce, where it was conceived).

I didn't spend a lot of time on naming, in the hopes it will be short-lived. Docs are online. It should be considered experimental, but it is rapidly approaching stability. Feedback, suggestions, and contributions are desperately appreciated.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!