2015-09-25 78 views
2

在下面的Python 3.5代码中,我想使用小于运算符(<)来比较两个通用值。我如何在T上声明一个约束来支持__lt__如何在泛型类型上声明Python约束来支持__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<T> where T:IComparable<T>

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

+0

为什么人们会觉得静态类型动态语言的冲动?顺便说一句,你为什么不尝试首先定义'__ge__'('__ge__'是'__lt__'的右侧版本)。 “this_works”的工作原理是因为所有类都定义了__eq__。 – JBernardo

+1

@JBernardo“为什么人们会觉得静态类型动态语言的冲动?” - 因为它有很多优点。 –

回答

1

更新 - 在mypy下面的场景的最新版本(验证0.521)正确处理。


嗯,我一直在寻找同样的问题,事实证明,你可以通过额外的参数boundTypeVar实现自己的目标,如PEP484描述:从提到PEP

A type variable may specify an upper bound using bound=<type> . This means that an actual type substituted (explicitly or implicitly) for the type variable must be a subtype of the boundary type. A common example is the definition of a Comparable type that works well enough to catch the most common errors:

示例代码:

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 
+0

FWIW这不与typyheck与mypy 0.470:'错误:类型参数1的“min”具有不兼容的值“int”' –

+0

嗯,是的,这是正确的。但除了缺少工具支持之外,这应该是一段路要走(这对OP来说可能不太有用) – Yakuza