你想让某个类的实例支持标准的比较运算(比如>=,!=,<=,<等),但是又不想去实现那一大丢的特殊方法。
Python类对每个比较操作都需要实现一个特殊方法来支持。 例如为了支持>=操作符,你需要定义一个 ge() 方法。 尽管定义一个方法没什么问题,但如果要你实现所有可能的比较方法那就有点烦人了。
装饰器 functools.total_ordering 就是用来简化这个处理的。 使用它来装饰一个来,你只需定义一个 eq() 方法, 外加其他方法(lt(<), le(<=), gt(>), or ge(>=))中的一个即可。 然后装饰器会自动为你填充其它比较方法。
作为例子,我们构建一些房子,然后给它们增加一些房间,最后通过房子大小来比较它们:
from functools import total_ordering
class Room:
def __init__(self, name, length, width):
self.name = name
self.length = length
self.width = width
# 不需要传参的就不用在括号里面写了
self.square_feet = self.length * self.width
@total_ordering
class House:
def __init__(self, name, style):
self.name = name
self.style = style
self.rooms = list()
def add_room(self, room):
self.rooms.append(room)
@property
def living_space_footage(self):
# 因为property 可以直接这样调用函数
return sum(r.square_feet for r in self.rooms)
# 最后想要输出什么样的结果
def __str__(self):
return '{}: {} square foot {}'.format(self.name,
self.living_space_footage,
self.style)
def __eq__(self, other):
# 因为传入了property ,所以直接加点调用就可以了。
return self.living_space_footage == other.living_space_footage
def __lt__(self, other):
return self.living_space_footage < other.living_space_footage
# Build a few houses, and add rooms to them
h1 = House('h1', 'Cape')
h1.add_room(Room('Master Bedroom', 14, 21))
h1.add_room(Room('Living Room', 18, 20))
h1.add_room(Room('Kitchen', 12, 16))
h1.add_room(Room('Office', 12, 12))
h2 = House('h2', 'Ranch')
h2.add_room(Room('Master Bedroom', 14, 21))
h2.add_room(Room('Living Room', 18, 20))
h2.add_room(Room('Kitchen', 12, 16))
h3 = House('h3', 'Split')
h3.add_room(Room('Master Bedroom', 14, 21))
h3.add_room(Room('Living Room', 18, 20))
h3.add_room(Room('Office', 12, 16))
h3.add_room(Room('Kitchen', 15, 17))
houses = [h1, h2, h3]
print('Is h1 bigger than h2?', h1 > h2) # prints True
print('Is h2 smaller than h3?', h2 < h3) # prints True
print('Is h2 greater than or equal to h1?', h2 >= h1) # Prints False
print('Which one is biggest?', max(houses)) # Prints 'h3: 1101-square-foot Split'
print('Which is smallest?', min(houses)) # Prints 'h2: 846-square-foot Ranch'
题目练习
读入 n(>0)名学生的姓名、学号、成绩,分别输出成绩最高和成绩最低学生的姓名和学号。
输入格式:
每个测试输入包含 1 个测试用例,格式为
第 1 行:正整数 n
第 2 行:第 1 个学生的姓名 学号 成绩
第 3 行:第 2 个学生的姓名 学号 成绩
… … …
第 n+1 行:第 n 个学生的姓名 学号 成绩
其中姓名和学号均为不超过 10 个字符的字符串,成绩为 0 到 100 之间的一个整数,这里保证在一组测试用例中没有两个学生的成绩是相同的。
输出格式:
对每个测试用例输出 2 行,第 1 行是成绩最高学生的姓名和学号,第 2 行是成绩最低学生的姓名和学号,字符串间有 1 空格。
输入样例:
3
Joe Math990112 89
Mike CS991301 100
Mary EE990830 95
输出样例:
Mike CS991301
Joe Math990112
代码思路:进行类的比较,需要导入total_ordering,这样比较两个对象就可以了;将所有的实例对象都放在一个列表里,重新建造输入函数__str__,就可以输出想要的结果了。
from functools import total_ordering
@total_ordering
class Student:
def __init__(self, name, id, score):
self.name = name
self.id = id
self.score = score
def __eq__(self, other):
return self.score == other.score
def __lt__(self, other):
return self.score < other.score
def __str__(self):
return "{0} {1}".format(self.name, self.id)
n = input()
lst = []
for i in range(int(n)):
line = input()
line = line.split(" ")
s = Student(line[0], line[1], int(line[2]))
lst.append(s)
print(max(lst))
print(min(lst))
###############运行结果####################
3
Joe Math990112 89
Mike CS991301 100
Mary EE990830 95
Mike CS991301
Joe Math990112
总结:Python里面一切皆对象,所以对象也可以作为函数的参数使用。