7-5 How to make a class support comparison operations

__lt__ is less than, __le__ is less than or equal to, __gt__ is greater than, __ge__ is greater than or equal to, __eq__ is equal to, __ne__ is not equal to

class Rectangle(object):
    def __init__(self,w,h):
        self.w = w
        self.h = h

    def area(self):
        return self.w * self.h

    def __lt__(self,obj):
        print('in __lt__')
        return self.area()<obj.area

r1 = Rectangle(2.2,3.2)
r2 = Rectangle(2.1,3.3)

print (r1<r2) # r1.__lt__(r2) #When r1<r2 is called, r1 actually calls the __lt__(r2) method, and r2 is used as a parameter

Output result:

True

>>> 

If you want to implement these methods, you can overload these methods. If you use total_ordering to simplify the process, you can only define less than and equal to, and you can automatically generate other operator overloads.

>>> help(total_ordering)
Help on function total_ordering in module functools:

total_ordering(cls)
Class decorator that fills in missing ordering methods
help(total_ordering)
from functools import total_ordering

@total_ordering
class Rectangle(object):
    def __init__(self,w,h):
        self.w = w
        self.h = h

    def area(self):
        return self.w * self.h

    def __lt__(self,obj):
        print('in __lt__')
        return self.area()<obj.area()
    def __ge__(self,obj):
        print('in __ge__')
        return self.area() == obj.area()
    """
    <= > >= != are all judged by less than and equal logic
    """

r1 = Rectangle(4,3)
r2 = Rectangle(4,2)

print (r1<r2) #r1.__lt__(r2)

Output result:

False

>>>

 

If you define other graphics for comparison, other graphics without overloaded operators can only be used as parameters, not as callers. If you define a circle object c1 (without overloaded operators), then r1<c1 will return True or False, an exception will be thrown if c1<r1.

If the operator is overloaded when defining other graphics, it is too troublesome. You can define a common base class sheap for these graphs, and implement overloaded operator functions in the base class. An additional abstract interface area is defined, which can be compared, and all implement this abstract interface area

>>> from abc import ABCMeta
>>> from abc import abstractmethod
>>> help(abstractmethod)
Help on function abstractmethod in module abc:

abstractmethod(funcobj)
    A decorator indicating abstract methods.
    
    Requires that the metaclass is ABCMeta or derived from it.  A
    class that has a metaclass derived from ABCMeta cannot be
    instantiated unless all of its abstract methods are overridden.
    The abstract methods can be called using any of the normal
    'super' call mechanisms.
    
    Usage:
    
        class C:
            __metaclass__ = ABCMeta
            @abstractmethod
            def my_abstract_method(self, ...):
                ...
help(abstractmethod)
from functools import total_ordering    # total_ordering can simplify overloaded operators 
from abc import ABCMeta, abstractmethod #define virtual functions using @total_ordering 
#decorator         class shape(object):


    
    @abstractmethod #Decorator      def area (self):      #Define 
    virtual functions, those who inherit this class must implement pass
        
    
    def __lt__(self,obj):
        print('in __lt__')
        if not isinstance(obj,shape):    #判断obj是不是shape类型不是抛出异常
            raise TypeError('obj is not shape')
        return self.area()<obj.area()
    def __ge__(self,obj):
        print('in __ge__')
        if not isinstance(obj,shape):
            raise TypeError('obj is not shape')
        return self.area() == obj.area()

    
class Rectangle(shape):
    def __init__(self,w,h):
        self.w = w
        self.h = h

    def area(self):
        return self.w * self.h

class Circle(shape):
    def __init__(self,r):
        self.r = r

    def area(self):
        return self.r ** 2 * 3.14

r1 = Rectangle(4,3)
c1 = Circle(2)

print (c1<r1) #r1.__lt__(r2)

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325818513&siteId=291194637