Как в аннотации типов указать, что тип должен реализовывать какой-то конкретный метод?

Рейтинг: 0Ответов: 1Опубликовано: 09.04.2023

Как в аннотации типов указать, что тип должен реализовывать какой-то конкретный метод?

Чаще всего это нужно для специальных методов (например, __gt__ означает что объекты можно сравнивать через оператор >).

К примеру, мы пишем функцию get_max (упрощённый аналог встроенной функции max):

def get_max(l: list[...]) -> ...:
    cond = l[0]
    for cur in l:
        if cur > cond:
            cond = cur
    return cond

На месте ... должна быть аннотация типа, показывающая, что тип поддерживает сравнение с помощью оператора > (больше). Какой она должна быть?

Ответы

▲ 0Принят

Начиная с версии Python3.8 (PEP 544) доступен такой способ:

Сначала нужно определить класс, наследующий от typing.Protocol и реализующий нужный метод:

class SupportsGreaterThan(typing.Protocol):
    def __gt__(self, other): ...

Потом определить такой TypeVar:

GT = typing.TypeVar('GT', bound=SupportsGreaterThan)

И, наконец, использовать его в своей функции:

def get_max(l: list[GT]) -> GT:
    ...  # Реализация такая же

После всех этих действий Mypy предупреждает о неверном типе:

При таком коде:

get_max([1, 2, 3])
get_max([None, None])  # None нельзя сравнивать с помощью оператора `>`!

Он выводит:

main.py:20: error: Value of type variable "GT" of "get_max" cannot be "None"  [type-var]
Found 1 error in 1 file (checked 1 source file)