Python typing: Creating Tuple type at runtime

965 Views Asked by At

I want to create a type that is a tuple that contains 5 floats and an int. I can do this in the following way which works nicely.

from typing import Tuple

MyT = Tuple[float, float, float, float, float, int]
t: MyT = (1.0, 1.0, 1.0, 1.0, 1.0, 5)

But if I want even more floats it will become annoying having to type the same over and over. Is there a way to create such a type in a parametrized way? I know that passing a tuple to Tuple[] works as well, i.e.

MyT = Tuple[(float, float, float, float, float, int)]
t: MyT = (1.0, 1.0, 1.0, 1.0, 1.0, 5)

Therefore, I tried the following.

tup = ((float, ) * 5) + (int, )
MyT = Tuple[tup]

t: MyT = (1.0, 1.0, 1.0, 1.0, 1.0, 5)

But this fails type checking with mypy. I guess it is because the tuple that is passed to Tuple[] is created only at runtime? Is there a similar way that would work? Tested using Python 3.8.6 and MyPy 0.782.

1

There are 1 best solutions below

0
On BEST ANSWER

There is no way to automate the process of creating a tuple type hint or to create a tuple type where the number of items is parameterizable: you need to write out all five float types manually like you did in your first example.

Instead, I recommend you create a class instead:

class MyT:
    def __init__(self, a: List[float], b: int) -> None:
        self.a = a
        self.b = b

You can express this class more compactly using dataclasses if you prefer:

from dataclasses import dataclass

@dataclass
class MyTVersion2:
    a: List[float]
    b: int

Using either a class or dataclass should let you directly support storing a variable number of floats while also making the structure of your data easier for others to understand.

If it's important that you use specifically a tuple, I think the only options you have are to:

  1. Settle for manually writing creating a new type alias for each kind of tuple you want to use.
  2. Settle for something like Tuple[Any, ...]. Doing Tuple[float, ...] may also actually work for your specific example -- iirc mypy considers ints to be a subtype of floats.