我觉得这个问题以前一定被问过,但我找不到答案。
假设我想要实现一个Python类,该类的对象可以用sorted()
进行排序。我必须重新实现__lt__()
、__gt__()
等所有方法吗。?最低限度是多少?换句话说,sorted()
调用哪种方法进行排序?
根据文档:
排序(*,key=None,reverse=False(
此方法对列表进行适当排序,只使用<项目之间的比较。异常不会被抑制-如果任何比较操作失败,整个排序操作将失败(列表可能会处于部分修改状态(。
所以您只需要为类定义def __lt__(self,other):
。
另请参阅底部附近的排序HOW-TO:
在两个对象之间进行比较时,保证排序例程使用
__lt__()
。因此,通过定义一个__lt__()
方法可以很容易地将标准排序顺序添加到类中:
有一个functools
内置方法total_ordering
,它可以修饰类,并使其实例能够在没有关键函数规范的情况下传递给sorted((。
该类的唯一要求是定义任何一个比较dunder方法和__eq__
。
例如:
from functools import total_ordering
@total_ordering
class Sortable:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return self.x, self.y
def __lt__(self, obj):
return self.y < obj.y
def __eq__(self, obj):
return self.y == obj.y
obj_1 = Sortable("Hello", 9)
obj_2 = Sortable("World", -2)
obj_3 = Sortable("!", 5.5)
print(sorted([obj_1, obj_2, obj_3])
哪个输出:
>>> [("World", -2), ("!", 5.5), ("Hello", 9)]
只需要__lt__
。参见以下示例:
class MyCustomNumber:
def __init__(self, some_number):
self.some_number = some_number
def __lt__(self, other):
return self.some_number < other.some_number
list_ = [MyCustomNumber(1), MyCustomNumber(5), MyCustomNumber(-3), MyCustomNumber(150)]
for x in sorted(list_):
print(x.some_number)
输出:
-3
1
5
150
即使是sorted(list_, reverse=True)
也只能在实现__lt__
的情况下工作。