如何在泛型类型上声明 Python 约束以支持 __lt__?

pro*_*ave 8 generics types python-3.x

在下面的 Python 3.5 代码中,我想使用小于运算符 ( <) 来比较两个通用值。如何声明对 T 的约束以支持__lt__

from typing import *
import operator 

T = TypeVar('T')

class MyList(Generic[T]):
    class Node:
        def __init__(self, k:T) -> None:
            self.key = k 
            self.next = None  # type: Optional[MyList.Node]

    def __init__(self) -> None:
        self.root = None # type: Optional[MyList.Node]

    def this_works(self, val:T) -> bool:
        return self.root.key == val 

    def not_works(self, val:T) -> bool:
        return operator.lt(self.root.key, val)
Run Code Online (Sandbox Code Playgroud)

我正在使用Mypy进行类型检查,但失败not_works并显示以下消息:

$ mypy test.py
test.py: note: In member "not_works" of class "MyList":
test.py:20: error: Unsupported left operand type for < ("T")
Run Code Online (Sandbox Code Playgroud)

其他语言支持对 T 的约束。

在 C# 中: class MyList<T> where T:IComparable<T>

在 Java 中: class MyList<T extends Comparable<? super T>>

Yak*_*uza 13

您可以通过向 传递额外参数bound来实现您的目标TypeVar,如PEP484 中所述

类型变量可以使用 指定上限bound=<type>。这意味着替换(显式或隐式)类型变量的实际类型必须是边界类型的子类型。一个常见的例子是 Comparable 类型的定义,它可以很好地捕获最常见的错误:

来自上述 PEP 的示例代码:

from typing import TypeVar

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

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

def min(x: CT, y: CT) -> CT:
    if x < y:
        return x
    else:
        return y

min(1, 2) # ok, return type int
min('x', 'y') # ok, return type str
Run Code Online (Sandbox Code Playgroud)

在mypy的最新版本(用0.521验证)中,正确处理了上述场景。