mypy icon indicating copy to clipboard operation
mypy copied to clipboard

Tuple-like Sequence

Open llchan opened this issue 4 years ago • 3 comments

There are situations where a variable can be either a list or a tuple (or more generally, a sequence), but it is used/unpacked in a tuple-like way. That is, the length is fixed and types are possibly heterogeneous. A practical example of this is mpi4py's buffer specifications.

I don't believe it's possible to express a fixed-length heterogeneous sequence without using Tuple and forcing a specific type/inheritance. It'd be useful to have an abstract type that expresses tuple semantics without the inheritance bounds. So the analogy is roughly: List is to Sequence as Tuple is to FixedSequence (or whatever name we choose).

def foo(x: FixedSequence[int, str]) -> int:
    return x[0]

foo((0, ''))
foo([0, ''])

Currently I think it's necessary to do Sequence[Union[int, str]] and this loses both the fixed length and the ordering of the elements in the sequence.

llchan avatar Feb 25 '20 21:02 llchan

I've encountered cases where something like this would have been useful.

A possible implementation would generalize the internal TupleType type to support other tuple-like types, with different fallback types. List expression type inference should also be modified to look for these new types in the type context.

The priority seems pretty low right now, however. If somebody writes a PEP draft about this feature and it gains some interest from the community, we'd likely increase the priority.

JukkaL avatar Feb 28 '20 16:02 JukkaL

Python 3.9's Annotated gets us closer to the fixed-length part. Something like:

from collections.abc import Sequence
from typing import Annotated, TypeAlias

TTwoItem: TypeAlias = Annotated[Sequence[int], 2]

some_list: TTwoItem = [1, 2]
some_tuple: TTwoItem = (1, 2)
some_incorrect_tuple: TTwoItem = (1, 2, 3)  # A possible future mypy would error here

Note this would not accommodate the type heterogeneity aspect of this request.

jamesbraza avatar Nov 23 '22 17:11 jamesbraza

TTwoItem: TypeAlias = Annotated[Sequence[int], 2]

Could also be used to specify a range of valid lengths, e.g.

TTwoOrThreeInts: TypeAlias = Annotated[Sequence[int], range(2, 4)]

would specify a sequence with either 2 or 3 items.

kwikwag avatar Dec 27 '22 15:12 kwikwag

Just chiming in that I'd love to be able to have code like this pass type checks, and I think this request would be perfect for my case:

dict([[1,2]))

dict(["aa", "gg", "tt", "cc"])

dimaqq avatar Mar 01 '24 07:03 dimaqq