让类支持比较操作
有时我们希望自定义类,实例间可以使用<,<=,>,>=,==,!=号进行比较,我们自定义比较行为。
例如,有一个矩形类,我们希望比较两个矩形的实例时,比较的是面积。
class Rectangle: def __init__(self,w,h): self.w=w self.h=h def area(self): return self.w*self.h rect1 = Rectangle(5,3) rect2 = Rectangle(4,4) rect1 > rect2 # => rect1.area() > rect2.area()
比较运算符方法的重载,需要实现以下方法:
__lt__,__le__,__gt__,__ge__,__eq__,__ne__
使用标准库下的functools下的类装饰器total_ordering可以简化此过程
利用total_ordering装饰器可不必全部重载以上类似__lt__的方法,而是__lt__ & __eq__两个即可,
total_ordering会根据这两个方法推算出其他方法。
本例还将类抽象了出来,任何两个相比较的类都继承Shape类,Shape类提供一个抽象方法即area,
通过各种形状的面积来比较各对象的大小,在Shape类中只重载了__lt__ & __eq__,并用了装饰器total_ordering
from functools import total_ordering from abc import ABCMeta, abstractmethod @total_ordering class Shape(object): """docstring for Shape""" @abstractmethod def area(self): pass def __lt__(self, obj): if not isinstance(obj, Shape): raise TypeError("It's not Shape") return self.area() < obj.area() def __eq__(self, obj): if not isinstance(obj, Shape): raise TypeError("It's not Shape") return self.area() == obj.area() class RectangleCompare(Shape): """docstring for RectangleCompare""" def __init__(self, w, h): self.w = w self.h = h def area(self): return self.w * self.h class Circle(Shape): """docstring for Circle""" def __init__(self, r): self.r = r def area(self): return self.r ** 2 * 3.14 rc1 = RectangleCompare(2,9) rc2 = RectangleCompare(3,4) c1 = Circle(2) c2 = Circle(3) print rc1>=rc2 print c1.r,' ',c1.area() print rc1.area(),' ',c2.area() print rc1>c2 print rc2==1 运行结果: TrueTraceback (most recent call last): File "D:\python space\classCompare.py", line 49, in <module> True 2 12.56 18 28.26 False print rc2==1 File "D:\python space\classCompare.py", line 18, in __eq__ raise TypeError("It's not Shape") TypeError: It's not Shape