2015-09-25 33 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