我如何暗示类型与打字相当

tah*_*ith 12 python python-3.x

假设我想写一个比较排序函数,我可以提示输入必须是一个序列 with Sequence[T](或MutableSequence[T]在这种情况下)。

from typing import MutableSequence, T

def comparison_sort(s: MutableSequence[T]) -> None:
    pass
Run Code Online (Sandbox Code Playgroud)

然而,似乎没有一种开箱即用的方式来暗示T必须具有可比性。(似乎没有ComparableOrdered任何东西typing。)我怎样才能做到这一点?我想避免指定一组特定的类型,例如int, float, 'str` 以便用户也可以暗示他们自己的类型是可比较的。

Sha*_*ger 12

正如评论中所指出的,Comparable它不是一种存在状态,它仅作为一对类型的描述符才有意义。通常,排序函数使用同构类型,因此只要您不介意类型检查器只处理“支持<某些类型”而不是“支持<任意类型”的概念,您就可以定义自己的Comparable和绑定了typing TypeVar它。方便的是,PEP484(定义typing提示)已经提供了一个示例,说明您将如何执行此操作

from abc import ABCMeta
from typing import Any, TypeVar

class Comparable(metaclass=ABCMeta):
    @abstractmethod
    def __lt__(self, other: Any) -> bool: ...

CT = TypeVar('CT', bound=Comparable)
Run Code Online (Sandbox Code Playgroud)

然后,您可以将其用于您的comparable_sort定义:

def comparable_sort(s: MutableSequence[CT]) -> None:
Run Code Online (Sandbox Code Playgroud)

请注意,我只需要__lt__被定义;通常,Python 3 完全根据__lt__(它不使用任何其他丰富的比较器运算符,甚至不使用__eq__† 来实现自己的排序功能,因此以相同的方式设计自己的算法是个好主意,所以任何事情sorted可以处理,你可以用同样的方式处理。

:Python 2 最初__le__至少在一个地方 ( heapq) 使用,但它一直有意地、始终如一地__lt__用于 Python 3 时间范围内的内置函数和标准库,而且您的输入风格无论如何都只适用于 Python 3。

  • 是否可以在“__lt__”中使用“Any”以外的其他内容,即仅匹配“相同”类型的内容?或者我们可以使其通用并使用前向引用字符串,例如 `Comparable[T] ` 和 `class UserType(Comparable['UserType']): pass` (5认同)

Paw*_*bin 6

此版本适用于当前mypy版本。

基于typingrepo 中的线程:https : //github.com/python/typing/issues/59

from __future__ import annotations

from abc import abstractmethod
from typing import MutableSequence, Protocol, TypeVar


class Comparable(Protocol):
    """Protocol for annotating comparable types."""

    @abstractmethod
    def __lt__(self: CT, other: CT) -> bool:
        pass


CT = TypeVar("CT", bound=Comparable)

def comparison_sort(s: MutableSequence[CT]) -> None:
    pass


comparison_sort([1, 2, 3])  # OK
comparison_sort([1.0, 2.0, 3.0])  # OK
comparison_sort(["42", "420", "2137"])  # OK
comparison_sort([1, 2, "3"])  # mypy error 
Run Code Online (Sandbox Code Playgroud)

链接到 Github 要点。

  • 我当然赞成像你一样使用协议,而不是像其他答案中那样使用 ABC (2认同)