首页 > 其他 > 详细

如何让类支持比较操作?

时间:2020-07-23 02:08:17      阅读:106      评论:0      收藏:0      [点我收藏+]

需求:
有时我们希望自定义类,实例间可以使用<,<=,>,>=,==,!=,符号进行比较,我们自定义比较的行为,例如,有一个矩形的类,我们希望比较两个矩形的实例时,比较的是他们的面积。

class Rectangel:
    def __init__(self,w,h):
        self.w = W
        self.h = h

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

rect1 = Rectangel(5,3)
rect2 = Rectangel(4.4)
rect1 > rect2  # => rect1.area() > rect2.area()

思路
1、比较符号运算符重载,需要实现以下方法
__lt__,__le__,__gt__,__ge__,__eq__,__ne_
2、使用标准库下的functools下类装饰器total_ordering可以简化此过程

代码:

方法1:
class Rectangel:
    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 __le__(self,obj):
        print(‘in__le__‘)
        return self.area() <= obj.area()
rect1 = Rectangel(5,3)
rect2 = Rectangel(4,4)
#rect1 > rect2  # => rect1.area() > rect2.area()

print(rect1 < rect2) # rect1.__lt__(rect2)
print(rect1 <= rect2)

方法二:
from functools import total_ordering

@total_ordering
class Rectangel:
    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 __eq__(self,obj):
        print(‘in__eq__‘)
        return self.area() == obj.area()

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

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


rect1 = Rectangel(5,3)
rect2 = Rectangel(4,4)
c1 = Circle(3)

#rect1 > rect2  # => rect1.area() > rect2.area()
print(rect1 < c1)
print(c1 > 1)
print(rect1 < rect2) # rect1.__lt__(rect2)
print(rect1 >= rect2)

方法三:
from functools import total_ordering
from abc import ABCMeta, abstractmethod

@total_ordering
class Shape(object):  # 把运算符重载的函数都放到公共的抽象基类中,这样可以避免其他的类都要写运算符的函数,其他的函数中只要实现area()的方法就可以了
                      # 再定义一个抽象的接口,能比较的都要实现这个area,否则不能进行比较
    @abstractmethod
    def area(self):   # 描述一下抽象的接口,它的子类都要实现这个接口
        pass

    def __lt__(self,obj):
        print(‘in__lt__‘)
        if not isinstance(obj,Shape):
            raise TypeError(‘obj is not Shape‘)
        return self.area() < obj.area()

    def __eq__(self,obj):
        if not isinstance(obj,Shape):
            raise TypeError(‘obj is not Shape‘)
        print(‘in__eq__‘)
        return self.area() == obj.area()


class Rectangel(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


rect1 = Rectangel(5,3)
rect2 = Rectangel(4,4)
c1 = Circle(3)

#rect1 > rect2  # => rect1.area() > rect2.area()
print(rect1 < c1)
print(c1 > rect2)
print(rect1 < rect2) # rect1.__lt__(rect2)
print(rect1 >= rect2)

如何让类支持比较操作?

原文:https://www.cnblogs.com/Richardo-M-Q/p/13363736.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!