2017-12-25 20 views
1

값이 상한 및 하한을 갖도록 표현하고 해당 경계를 적용하기 위해 제네릭 클래스를 만들려고합니다.mypy와 비교할 수있는 유형

error: Unsupported left operand type for <= ("T") 

분명히 입력 모듈이 (가 looks likeComparable을 추가하는 것은 미래에 일어날 수도 있지만) 내가이 표현하는 것을 허용하지 않습니다

from typing import Any, Optional, TypeVar 

T = TypeVar("T") 

class Bounded(object): 
    def __init__(self, minValue: T, maxValue: T) -> None: 
     assert minValue <= maxValue 
     self.__minValue = minValue 
     self.__maxValue = maxValue 

그러나, mypy는 불평.

적어도 객체에 __eq____lt__ 개의 메소드가 있는지 확인하는 것만으로 충분하다고 생각합니다 (적어도 내 용도에 해당). Mypy가 이해할 수 있도록 Python에서이 요구 사항을 표현할 방법이 있습니까?

답변

2

좀 더 연구를 마친 후 해결책을 찾았습니다. 프로토콜. 완전히 안정적이지는 않지만 (아직 Python 3.6), 모듈은 typing_extensions 모듈에서 가져와야합니다.

import typing 
from typing import Any 
from typing_extensions import Protocol 
from abc import abstractmethod 

C = typing.TypeVar("C", bound="Comparable") 

class Comparable(Protocol): 
    @abstractmethod 
    def __eq__(self, other: Any) -> bool: 
     pass 

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

    def __gt__(self: C, other: C) -> bool: 
     return (not self < other) and self != other 

    def __le__(self: C, other: C) -> bool: 
     return self < other or self == other 

    def __ge__(self: C, other: C) -> bool: 
     return (not self < other) 

이제 우리는 우리의 유형을 정의 할 수 있습니다와 같은 :

C = typing.TypeVar("C", bound=Comparable) 

class Bounded(object): 
    def __init__(self, minValue: C, maxValue: C) -> None: 
     assert minValue <= maxValue 
     self.__minValue = minValue 
     self.__maxValue = maxValue 

그리고 Mypy는 행복하다 :

from functools import total_ordering 

@total_ordering 
class Test(object): 
    def __init__(self, value): 
     self.value = value 
    def __eq__(self, other): 
     return self.value == other.value 
    def __lt__(self, other): 
     return self.value < other.value 

FBounded(Test(1), Test(10)) 
FBounded(1, 10)