要重新定义哪些 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)]
我觉得这个问题一定有人问过,但我找不到答案。
假设我想实现一个 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)]