2

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
    You can use `Tuple[float, ...]` to accept any number of numeric values. (See [here](https://stackoverflow.com/q/43957034/3282436) regarding whether to use `int`/`float` for the type parameter.) It doesn't make sense to create type hints at runtime since they are designed for linters to validate pre-runtime. – 0x5453 Oct 02 '20 at 16:12
  • it assumes all are float. there is int in the type. – Dyno Fu Oct 02 '20 at 16:12
  • Note, passing a tuple doesn't work "as well", it's already what you are doing here: `Tuple[float, float, float, float, float, int]`, i.e., the commas make the tuple, not the parentheses in `Tuple[(float, float, float, float, float, int)]`. In any case, what is it that you are trying to avoid, exactly? Why would you have to type this over-and-over, it looks like you are already using an alias, wouldn't you just use the alias over and over? – juanpa.arrivillaga Oct 02 '20 at 16:22
  • Does this answer your question? [Specify length of Sequence or List with Python typing module](https://stackoverflow.com/questions/44833822/specify-length-of-sequence-or-list-with-python-typing-module) – Georgy Oct 02 '20 at 21:54

1 Answers1

1

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.
Michael0x2a
  • 58,192
  • 30
  • 175
  • 224