要重新定义哪些 Python 对象比较方法才能使 sorted() 工作?

Which Python object comparison methods to redefine to make sorted() work?

我觉得这个问题一定有人问过,但我找不到答案。

假设我想实现一个 Python class,其对象可以用 sorted() 排序。我是否必须重新实现所有方法,如 __lt__()__gt__() 等?最低限度是多少?换句话说,sorted() 调用了哪种方法进行排序?

根据 documentation:

sort(*, key=None, reverse=False)
This method sorts the list in place, using only < comparisons between items. Exceptions are not suppressed - if any comparison operations fail, the entire sort operation will fail (and the list will likely be left in a partially modified state).

所以你只需要为你的class定义def __lt__(self,other):

另请参阅底部附近的 Sorting HOW-TO

The sort routines are guaranteed to use __lt__() when making comparisons between two objects. So, it is easy to add a standard sort order to a class by defining an __lt__() method:

只需要__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__ 实现的情况下工作。

有一个 functools 内置方法 total_ordering 可以装饰你的 class 并使其实例能够传递给 sorted () 没有关键功能规范。

class 的唯一要求是定义任何比较 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)]