7-5 如何让类支持比较操作

__lt__小于、__le__小于等于、__gt__大于、__ge__大于等于、__eq__等于、__ne__不等于

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)  #调用r1<r2时实际上是r1调用__lt__(r2)方法,r2做为参数

输出结果:

True

>>> 

如果要实现这些可以运算符重载这些方法,如果使用total_ordering可以简化过程,只定义小于和等于,就可以,能自动生成其他的运算符重载

>>> 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()
    """
    <= > >= != 都是通过小于和等于逻辑判断出
    """

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

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

输出结果:

False

>>>

 

如果再定义其他图形做比较,其他图形如没重载运算符,只能做为参数,不能做为调用者,若定义 一个圆对象c1(没重载运算符),那么r1<c1会返回True或False,若c1<r1则会抛出一个异常。

如若定义 其他图形时都重载运算符又太麻烦。可以会这些图形定义一个公共基类sheap,在基类里实现重载运算符函数。额外定义一个抽象的接口area,能比较的,都实现这个抽象接口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 可以简化重载运算符
from abc import ABCMeta,abstractmethod #定义虚函数使用

@total_ordering        #装饰器
class shape(object):
    
    @abstractmethod     #装饰器
    def area(self):     #定义虚函数,继承此类的必须实现
        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)

猜你喜欢

转载自www.cnblogs.com/smulngy/p/9008446.html
7-5