Mypy:具有某些方法的通用容器仅在适用额外协议时才有效

Mypy: Generic container with some methods only valid if extra protocols apply

在 mypy 中,如何指定 T 之上的类型 Generic 具有仅在 T 满足特定条件时才有效的方法?

例如,如果我们使用 min 方法创建自定义集合 class,返回集合中的最小元素:

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)     

如何告诉类型系统只有在 T 实现了 __lt__ 的情况下才允许在 TMyCollection 上调用 min

所以基本上我希望通用容器的某些方法只有在满足额外协议时才有效。

-- 有用的链接 --

您可以从 typehints in the standardlib for min 中看到他们已经定义了一个协议来执行 __lt__ 已实施

class SupportsLessThan(Protocol):
    def __lt__(self, __other: Any) -> bool: ...

SupportsLessThanT = TypeVar("SupportsLessThanT", bound=SupportsLessThan)  # noqa: Y001

在您链接的同一个存根文件中,查看 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,您可以指定一个方法仅适用于泛型 class 的特定特化。您还可以在 mypy 文档中看到这个 documented

因此您的 min 将被注释为

def min(self: 'MyCollection[SupportsLessThanT]') -> SupportsLessThanT:
    ...

具有 SupportsLessThanT 的适当定义。