cd_riper (cd_riper) wrote,

Python -- добавляем операторы сравнения к типу

Абсолютно аналогичная картина. У типа есть некий метод сравнения, который принимает на вход объект своего типа и возвращается результат сравнения в виде int. Нужно заставить работать для этого типа шесть операторов сравнения.

Для операторов сравнения зарезервированы специальные имена методов -- __lt__, __le__ и т.д. Нам нужно добавить их определение к заданному типу.

Мне кажется, что удобнее всего задача решается с помощью декоратора для класса:


Copy Source | Copy HTML
def AddClassCompare(obj : type, cmpFn : FunctionType = None) -> None:
 
    assert isinstance(obj, type)
    cmpFn = cmpFn or obj.cmp
 
    def GetFn(cmpInPlace):
 
        def Fn(self, other):
            x = cmpFn(self, other)
            return cmpInPlace(x)
 
        return Fn
 
    obj.__lt__ = GetFn(lambda x: x <  0)
    obj.__le__ = GetFn(lambda x: x <=  0)
    obj.__eq__ = GetFn(lambda x: x ==  0)
    obj.__ne__ = GetFn(lambda x: x !=  0)
    obj.__gt__ = GetFn(lambda x: x >  0)
    obj.__ge__ = GetFn(lambda x: x >=  0)
 
# compare decorator        
def ComparableClass(cmpFn : FunctionType = None) -> FunctionType:
 
    def fn(obj : type) -> type:
        assert isinstance(obj, type)
        objCopy = copy.copy(obj) # is that make sense? 
        AddClassCompare(objCopy, cmpFn)
        return objCopy
 
    if cmpFn: assert isinstance(cmpFn, FunctionType)
 
    return fn
 
# -----------------------------------------------------     
 
def Test_ComparableClass():
 
    class A:
        def __init__(self, val =  0):
            self.val = val
 
        def Compare(self, other):
            if self.val > other.val: return 1
            if self.val < other.val: return -1
            return  0
 
    @ComparableClass() # don't forget add "()"
    class B(A):
        def __init__(self, val =  0):
            A.__init__(self, val)
 
        def cmp(self, other):
            return A.Compare(self, other)
 
    @ComparableClass(lambda x, y: x.Compare(y)) # must use lambda, not direct C.Compare
    class C(A):
        def __init__(self, val =  0):
            A.__init__(self, val)
 
    def TestType(T : type):
        assert T(10) > T(3)
        assert T(3) <= T(3)
        assert not T(7) == T(3)
 
    TestType(B)
    TestType(C)
 
 


По-умолчанию для сравнения используется метод int cmp(other), но через параметр декоратора его можно изменить.

Операторы сравнения для C++ -- http://cd-riper.livejournal.com/270020.html


Грузоперевозки от 600 рублей: заказ газели.
Tags: programming, python
  • Post a new comment

    Error

    Comments allowed for friends only

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments