如何在Python中为嵌套泛型定义TypeAlias?

n3h0vuf2  于 2023-01-08  发布在  Python
关注(0)|答案(1)|浏览(178)

我现在有这个代码

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])))

但是我认为别名Grid中的T绑定到函数返回类型中的不同T
如何定义Grid,以便可以编写

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

我看过typing.GenericAlias,但看不出它对我有什么帮助。
(我知道Sequence[Sequence[T]]并不能保证网格实际上是矩形的,但这不是我在这里想关注的问题。)

ovfsdjhp

ovfsdjhp1#

当使用类型变量作为泛型参数时,它可以被其他类型变量替换,这在泛型别名类型中提到(但我只找到了这一个):
泛型容器的__getitem__()方法将引发一个异常,以禁止类似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]

然而,当使用类型变量时,这样的表达式是有效的。索引必须具有与GenericAlias对象的__args__中的类型变量项一样多的元素。

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

所以你当前的实现没有问题。在交互式解释器中,你会看到:

>>> 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也会正确地分析它们:

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)

相关问题