#python #types #mypy
#python #типы #mypy
Вопрос:
В mypy, как бы вы указали, что у типа Generic
over T
есть методы, которые допустимы только при T
соблюдении определенных условий?
Например, если мы создали пользовательский класс коллекции с min
помощью метода, возвращающего наименьший элемент в коллекции:
from typing import Generic, TypeVar
T = TypeVar("T")
class MyCollection(Generic[T]):
def __init__(self, some_list: List[T]):
self._storage = some_list
def min(self) -> T: # This requires that T implements __lt__
"Get the smallest element in the collection"
return min(self._storage)
Как вы можете сообщить системе типов, что вызов min
MyCollection
of T
разрешен только в случае T
реализации __lt__
?
Поэтому в принципе я хотел бы, чтобы некоторые методы универсального контейнера были действительны только при соблюдении дополнительных протоколов.
— Полезные ссылки —
Вы можете видеть из указателей типов в standardlib для min, что они определили протокол для принудительного __lt__
применения. реализован
class SupportsLessThan(Protocol):
def __lt__(self, __other: Any) -> bool: ...
SupportsLessThanT = TypeVar("SupportsLessThanT", bound=SupportsLessThan) # noqa: Y001
Комментарии:
1. Я не думаю, что система типов python поддерживает это
2. Просто для ясности: вы хотите, чтобы весь класс принимал только
T
те, которые поддерживают<
, или вы хотите, чтобы только конкретный метод принимал только такиеT
? В последнем случае вы ожидаете, что метод будет полностью отсутствовать или просто не вернется (вызовет ошибку)?
Ответ №1:
В том же файле-заглушке, который вы связали, посмотрите подсказки по типу для list.sort
:
class list(MutableSequence[_T], Generic[_T]):
...
@overload
def sort(self: List[SupportsLessThanT], *, key: None = ..., reverse: bool = ...) -> None: ...
@overload
def sort(self, *, key: Callable[[_T], SupportsLessThan], reverse: bool = ...) -> None: ...
С помощью подсказки типа self
вы можете указать, что метод применим только для определенных специализаций универсального класса. Вы также можете увидеть это задокументировано в документах mypy.
min
Таким образом, ваш будет помечен как
def min(self: 'MyCollection[SupportsLessThanT]') -> SupportsLessThanT:
...
с подходящим определением SupportsLessThanT
.