Зависимые типы и полиморфизм в Python с mypy - PullRequest
1 голос
/ 03 ноября 2019

В следующем примере mypy возвращает ошибку:

ошибка: несовместимые типы в присваивании (выражение имеет тип "A", переменная имеет тип "A1")

from typing import Type

class A:
    pass

class A1(A):
    pass

class A2(A):
    pass

def fun(A_type: Type[A]) -> A:
    if A_type == A1:
        return A1()
    else:
        return A2()

a1: A1 = fun(A1)

В идеале я хотел бы установить зависимость в сигнатуре fun:

def fun(A_type: Type[A]) -> A_type

Возможно ли это;если нет, что рекомендуется (примечание: я хочу, чтобы это работало для пока еще неопределенных подклассов A, поэтому я не думаю, что смогу использовать декоратор overload)? Мой лучший вариант просто использовать cast?

1 Ответ

2 голосов
/ 03 ноября 2019

Используйте TypeVar с ограничением на него:

https://mypy.readthedocs.io/en/latest/generics.html#type-variables-with-upper-bounds

from typing import Type, TypeVar

class A:
    pass

class A1(A):
    pass

class A2(A):
    pass

T_A = TypeVar('T_A', bound='A')

def fun(A_type: Type[T_A]) -> T_A:
    if A_type == A1:
        r1 = A1()
        assert isinstance(r1, A_type)
        return r1
    else:
        r2 = A2()
        assert isinstance(r2, A_type)
        return r2

a1: A1 = fun(A1)
a2: A2 = fun(A2)
print("winner winner chicken dinner")

Проверка типов очищается и запускается без сбоев, либо утверждение типа:

C:\test\python>mypy polymorph.py
Success: no issues found in 1 source file

C:\test\python>python polymorph.py
winner winner chicken dinner

Inв этом примере тип T_A должен быть подклассом A, но это особый тип , а тип fun требует, чтобы он возвращал тот же тип, который он получает в качестве аргумента.

К сожалению, статическая проверка типов не достаточно достаточно умна, чтобы связывать тип, если вы не добавите туда утверждение времени выполнения (может быть какой-то способ сделать это лучше с Genericтипа, но это ускользает от меня).

...