MyPy не позволяет ограниченным TypeVar быть ковариантными?Определение общего диктата с ограниченными, но ковариантными типами ключ-валь - PullRequest
0 голосов
/ 25 октября 2018

Я пытаюсь определить пользовательский общий dict, ключи которого имеют тип T_key, а значения имеют тип T_val.
Я также хочу наложить ограничения на T_key и T_val, напримерчто T_key может быть только типа A или B или их подкласса.

Как мне это сделать?

from typing import TypeVar, Generic

class A: ...
class B: ...

class Asub(A): ...
class Bsub(B): ...

T_key = TypeVar('T_key', A, B, covariant=True)
T_val = TypeVar('T_val', A, B, covariant=True)


class MyDict(Generic[T_key, T_val]): ...


w: MyDict[   A,    B]
x: MyDict[   A, Bsub]
y: MyDict[Asub,    B]
z: MyDict[Asub, Bsub]

Когда я пытаюсь это проверить, mypy даетошибки в аннотациях x, y и z.Только аннотация для w работает должным образом.

generic.py:17: error: Value of type variable "T_val" of "MyDict" cannot be "Bsub"
generic.py:18: error: Value of type variable "T_key" of "MyDict" cannot be "Asub"
generic.py:19: error: Value of type variable "T_key" of "MyDict" cannot be "Asub"
generic.py:19: error: Value of type variable "T_val" of "MyDict" cannot be "Bsub"

Я не понимаю, почему Asub не является допустимым типом для T_key, даже если указано covariant=True.

Чего мне здесь не хватает?

mypy версия: 0.630

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

решение:

Оказывается, что может принимать Союзы.

from typing import TypeVar, Generic, Union

class A: ...
class B: ...

class Asub(A): ...
class Bsub(B): ...



T_key = TypeVar('T_key', bound=Union[A, B])
T_val = TypeVar('T_val', bound=Union[A, B])


class MyDict(Generic[T_key, T_val]): ...


w: MyDict[   A,    B]  # passes
x: MyDict[   A, Bsub]  # passes
y: MyDict[Asub,    B]  # passes
z: MyDict[Asub, Bsub]  # passes
bad: MyDict[int, int]  # Type argument "builtins.int" of "MyDict" must be a subtype of "Union[generic.A, generic.B]"
0 голосов
/ 25 октября 2018

Это не то, что означает ковариация.С ковариантной переменной типа T и универсальным классом Foo[T] экземпляры Foo[Subclass] также считаются экземплярами Foo[Superclass].Ковариантность не влияет на то, какие типы могут быть заменены на T.

. Если ваш B был подклассом A, то значение типа MyDict[B, B] будет считаться также значением типаMyDict[A, A] статическими шашками из-за ковариации.Вы все равно не сможете создать значение типа MyDict[C, C], где C - это какой-то другой подкласс B или A.

Понятие, которое вы ищете, является ограниченнымПеременные типа с использованием ключевого аргумента bound, переменные типа без ограничений.Похоже, что вы можете указать объединение в качестве границы, что меня удивляет, поэтому объявление переменных типа как

T_key = TypeVar('T_key', bound=Union[A, B])
T_val = TypeVar('T_val', bound=Union[A, B])

должно работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...