【问题标题】:How to declare Python constraint on generic type to support __lt__?如何声明 Python 对泛型类型的约束以支持 __lt__?
【发布时间】:2015-09-25 17:14:35
【问题描述】:

在下面的 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)

我正在使用 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")

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

在 C# 中:class MyList&lt;T&gt; where T:IComparable&lt;T&gt;

在 Java 中:class MyList&lt;T extends Comparable&lt;? super T&gt;&gt;

【问题讨论】:

  • 为什么人们会有用静态类型动态语言的冲动?顺便说一句,你为什么不先尝试定义__ge____ge____lt__ 的右侧版本)。 "this_works" 有效,因为 __eq__ 是为所有类定义的。
  • @JBernardo “为什么人们会有将静态类型输入动态语言的冲动?” — 因为它有很多优点。

标签: python-3.x generics types


【解决方案1】:

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

类型变量可以使用bound=&lt;type&gt; 指定上限。这意味着替换(显式或隐式)类型变量的实际类型必须是边界类型的子类型。一个常见的例子是 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

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

【讨论】:

  • FWIW 这不会使用 mypy 0.470 进行类型检查:error: Type argument 1 of "min" has incompatible value "int"
  • 嗯,是的,没错。但除了缺乏工具支持之外,这应该是可行的方法(这可能对 OP 没有太大帮助)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-17
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
  • 2017-01-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多