Annotation with custom types derived from numerical types in Python

Question:

I am trying to create a custom type/class in Python that plays well with annotations and also can be checked in runtime.

The only way I was able to achieve this is by using TypeAlias.

from __future__ import annotations

import typing

FloatAlias: typing.TypeAlias = float

class FloatClass(float):
    pass

FloatNT = typing.NewType("FloatNT", float)

class AClass:

    a: FloatAlias = 1.23
    b: FloatClass = 1.23 # mypy complains
    c: FloatNT = 1.23    # mypy complains

# True
print(isinstance(3.4, FloatAlias))

# False
print(isinstance(3.4, FloatClass))

# TypeError: isinstance() arg 2 must be a type, a tuple of types, or a union
print(isinstance(3.4, FloatNT))

But the problem that in certain cases it is resolved back to float and I want to keep track the the user flag it with the custom class, and not with float. Is would rather have something like FloatClass or FloatNT. Is that possible?

EDIT

These new types are aim to provide additional context about the purpose or role of a user defined attribute. I would argue that if a user writes something like this the intent is clear:


class AClass:

    data1: MyFloat = 1.23
    data2: float = 4.56

  • MyFloat is just a thin layer over float
  • a Literal is being used

Therefore it would be nice to auto cast it.

However if then there is a function like this:

def do_something(x: MyFloat):
    # code

mypy should accept using data1 but not data2.

Asked By: Kim

||

Answers:

What I think you want is the NewType option, which does require that you explicitly initialize the values as the more specific type in order for mypy to accept them being assigned to variables of that type.

FloatNT = typing.NewType("FloatNT", float)

class AClass:
    c: FloatNT = FloatNT(1.23)

You might argue that if you say:

class AClass:
    data1: FloatNT = 1.23  # error!
    data2: float = 4.56

the intent is clear and so the type should automatically convert, but mypy does not automatically "convert" a less specific type to a more specific type, any more than it’ll automatically convert a type if you do something like:

class AClass:
    data1: bool = 1  # error!
    data2: bool = true
Answered By: Samwise
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.