Python中使用__cmp__与__lt__排序对象列表失败求助
如何正确为自定义Vertice类实现排序?
我帮你找出问题啦!你的代码排序失效主要有两个核心原因,咱们一步步拆解解决:
问题根源
- Python3已废弃
__cmp__方法:你写的__cmp__在Python3里不会被sort()调用,这个方法是Python2的遗留产物,完全起不到作用,可以直接删掉。 __lt__和__gt__返回值错误:这两个比较魔术方法需要返回布尔值(True/False),但你返回的是整数(-1、1、0)。Python会把非零整数视为True,这直接打乱了排序的判断逻辑,导致排序结果混乱。
修正后的代码实现
根据你“先按coordenada_x排序,再按coordenada_y排序”的需求,我们只需要正确实现__lt__方法即可(sort()默认依赖__lt__来确定元素顺序):
class Vertice: def __init__(self, coordenada_x, coordenada_y): self.coordenada_x = coordenada_x self.coordenada_y = coordenada_y def __str__(self): return "Vértice ({},{})".format(self.coordenada_x, self.coordenada_y) def __add__(self, otro_vertice): vertice_resultado = Vertice(self.coordenada_x + otro_vertice.coordenada_x, self.coordenada_y + otro_vertice.coordenada_y) return vertice_resultado # 核心:正确实现__lt__,先按x升序,x相同则按y升序 def __lt__(self, otro_vertice): if self.coordenada_x != otro_vertice.coordenada_x: return self.coordenada_x < otro_vertice.coordenada_x else: return self.coordenada_y < otro_vertice.coordenada_y import random def main(): lista = [] for i in range(0,10): a = random.randint(1,99) b = random.randint(1,99) lista.append(Vertice(a,b)) print("排序前:") for elemento in lista: print(elemento) print("\n排序后:") lista.sort() for elemento in lista: print(elemento) main()
额外优化:自动生成所有比较方法
如果你需要支持>、<=、>=等其他比较操作,可以用functools.total_ordering装饰器,只需要实现__lt__和__eq__,其他比较方法会自动生成,代码更简洁:
from functools import total_ordering import random @total_ordering class Vertice: def __init__(self, coordenada_x, coordenada_y): self.coordenada_x = coordenada_x self.coordenada_y = coordenada_y def __str__(self): return "Vértice ({},{})".format(self.coordenada_x, self.coordenada_y) def __add__(self, otro_vertice): vertice_resultado = Vertice(self.coordenada_x + otro_vertice.coordenada_x, self.coordenada_y + otro_vertice.coordenada_y) return vertice_resultado def __lt__(self, otro_vertice): if self.coordenada_x != otro_vertice.coordenada_x: return self.coordenada_x < otro_vertice.coordenada_x else: return self.coordenada_y < otro_vertice.coordenada_y def __eq__(self, otro_vertice): return (self.coordenada_x == otro_vertice.coordenada_x) and (self.coordenada_y == otro_vertice.coordenada_y) def main(): lista = [] for i in range(0,10): a = random.randint(1,99) b = random.randint(1,99) lista.append(Vertice(a,b)) print("排序前:") for elemento in lista: print(elemento) print("\n排序后:") lista.sort() for elemento in lista: print(elemento) main()
关于排序方向
- 如果需要降序排序,你可以直接在调用
sort()时加上参数:lista.sort(reverse=True),不需要修改__lt__方法。 - 或者也可以把
__lt__里的<改成>,直接实现降序的比较逻辑。
内容的提问来源于stack exchange,提问作者user1746636
相关产品推荐
相关产品推荐

