案例:
有时我们希望自定义的类,实例间可以使用<,<=,>,>=,==,!=符号进行比较,我们自定义比较的行为。例如:有一个矩形的类,我们希望比较两个矩形的实例时,比较的是他们的面积。
比较符号运算符重载,需要实现以下方法:
__lt__,__le__,__gt__,__ge__,__eq__,__ne__
使用标准库下的functools下的类装饰器total_ordering可以简化此过程,此装饰器是在python2.7的时候加上的,它是针对某个类中如果定义了__lt__、__le__、__gt__、__ge__这些方法中的至少一个,使用该装饰器,则会自动的把其他几个比较函数也实现在该类中
from math import pi
from functools import total_ordering
from abc import abstractmethod #调用抽象基类方法,让继承父类的子类实现父类的方法
@total_ordering #定义语法糖装饰器
class Shape(object):
@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): #定义相等方法
print('in__eq__')
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,radius):
self.radius = radius
def area(self):
return self.radius * 2 * pi
class Square(Shape): #计算正方形面积
def __init__(self, side):
self.side = side
def area(self):
return self.side * self.side
r1 = Rectangle(5,3)
s1 = Square(4)
c1 = Circle(3)
print(c1 <= r1) #r1.__lt__(r2)
print(c1 >= s1) #r1.__lt__(r2)
print(r1 == s1) #r1.__lt__(r2)
print(r1 != 1) #报错