0

I currently have this code

T = TypeVar("T")
Grid = Sequence[Sequence[T]]

def columns(grid: Grid) -> Iterable[list[T]]:
    return ([row[i] for row in grid] for i in range(len(grid[0])))

But I think the T in the alias Grid is bound to a different T in the return type of the function.

How do I define Grid such that I can write

def columns(grid: Grid[T]) -> Iterable[list[T]]:
    ...

I've looked at typing.GenericAlias, but can't see how it helps me.

(I'm aware that Sequence[Sequence[T]] has no guarantee that the grid is actually rectangular, but that's not the problem I want to focus on here.)

2
  • 1
    It looks good now. Sequence[Sequence[T]][R] will get Sequence[Sequence[R]]. Commented Jan 7, 2023 at 12:39
  • @MechanicPig That's correct! Can you turn your comment into an answer so I can accept it? Commented Jan 7, 2023 at 13:21

1 Answer 1

2

When using type variable as a generic parameter, it can be replaced by other type variables, which is mentioned in the Generic Alias Type (but I only found this one):

The __getitem__() method of generic containers will raise an exception to disallow mistakes like dict[str][str]:

>>> dict[str][str]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: There are no type variables left in dict[str]

However, such expressions are valid when type variables are used. The index must have as many elements as there are type variable items in the GenericAlias object’s __args__.

>>> from typing import TypeVar
>>> Y = TypeVar('Y')
>>> dict[str, Y][int]
dict[str, int]

So there is no problem with your current implementation. In the interactive interpreter, you will see:

>>> from collections.abc import Sequence
>>> from typing import TypeVar
>>> T, R = TypeVar('T'), TypeVar('R')
>>> Grid = Sequence[Sequence[T]]
>>> Grid
collections.abc.Sequence[collections.abc.Sequence[~T]]
>>> Grid[R]
collections.abc.Sequence[collections.abc.Sequence[~R]]

Mypy will also correctly analyze them:

from collections.abc import Sequence, Iterable
from typing import TypeVar

T = TypeVar('T')
Grid = Sequence[Sequence[T]]


def columns(grid: Grid[T]) -> Iterable[list[T]]:
    return ([row[i] for row in grid] for i in range(len(grid[0])))


c1: Iterable[list[int]] = columns([[1, 2, 3]])  # pass
c2: Iterable[list[int]] = columns([[4, 5, '6']])
# List item 2 has incompatible type "str"; expected "int" (13:42)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.