Python类要支持比较运算,必须显式实现__lt__、__le__、__eq__、__ne__、__gt__、__ge__中至少一个(通常为__lt__),否则直接比较会报TypeError。

Python 类要支持比较运算,必须显式实现 __lt__、__le__、__eq__、__ne__、__gt__、__ge__ 中的至少一个(通常是 __lt__),否则直接比较会报 TypeError: '。
为什么只实现 __lt__ 就能用 sorted() 和 list.sort()?
Python 的排序函数(如 sorted()、list.sort())内部只依赖小于关系(__lt__)做元素间两两比较。它不检查是否相等或大于,也不调用其他比较方法——哪怕你实现了 __eq__,排序过程也完全不会用到。
所以只要类定义了 __lt__,就能直接用于排序:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
<pre class='brush:python;toolbar:false;'>def __lt__(self, other):
return self.age < other.age # 按年龄升序people = [Person("Alice", 30), Person("Bob", 25)] sorted_people = sorted(people) # ✅ 正常工作
- 如果
__lt__返回NotImplemented(比如类型不匹配),Python 会尝试反向调用other.__gt__(self),但一般不建议依赖这个机制 - 返回值必须是布尔值;返回其他类型(如
int或None)会导致运行时行为异常或静默失败 -
__lt__必须处理other是非同类对象的情况,否则sorted([p1, "hello"])会抛出未捕获异常
@total_ordering 能省多少事?
如果你希望类支持所有六种比较运算符(、<code>==、!=、>、>=),又不想手动写五个方法,functools.total_ordering 是标准解法。
立即学习“Python免费学习笔记(深入)”;
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
它要求你至少实现 __eq__ 和「一个」有序比较方法(推荐 __lt__),然后自动生成其余四个:
from functools import total_ordering
<p>@total_ordering
class Score:
def <strong>init</strong>(self, value):
self.value = value</p><pre class='brush:python;toolbar:false;'>def __eq__(self, other):
return isinstance(other, Score) and self.value == other.value
def __lt__(self, other):
if not isinstance(other, Score):
return NotImplemented
return self.value < other.values1, s2 = Score(85), Score(92) print(s1 < s2) # True print(s1 <= s2) # True(自动生成) print(s1 == s2) # False(你写的 eq) print(s1 != s2) # True(自动生成)
- 没加
@total_ordering时,s1 会回退到 <code>not (s2 ,但这是 Python 默认逻辑,不是你定义的语义;加了装饰器后才真正按你定义的 <code>__lt__和__eq__推导其余行为 - 装饰器不会帮你写
__eq__,漏掉它会导致所有比较(包括==)都返回False - 生成的方法在遇到不支持类型时仍会返回
NotImplemented,所以__lt__和__eq__里自己做类型检查仍是必要的
常见错误:在 __lt__ 里用 self < other 递归调用
新手容易在 __lt__ 实现中误写成 return self ,这会无限递归,最终触发 <code>RecursionError: maximum recursion depth exceeded。
正确做法是基于具体字段比较,而不是再次调用自身:
# ❌ 错误:无限递归
def __lt__(self, other):
return self < other # 千万别这么写!
<h1>✅ 正确:拆解为字段比较</h1><p>def <strong>lt</strong>(self, other):
if not isinstance(other, MyClass):
return NotImplemented
return self.priority < other.priority- 这种错误在 PyCharm 或 VS Code 中通常没有语法提示,只有运行时崩
- 如果字段本身也支持比较(如
int、str),直接比就行;如果是嵌套对象,确保其也实现了__lt__ - 用
isinstance()做类型检查比type(self) == type(other)更健壮,能兼容子类
最易被忽略的一点:__lt__ 的实现必须满足**严格偏序**——即不能出现 a 这类循环,否则 <code>sorted() 行为未定义,可能崩溃、卡死或返回乱序结果。实际中,优先用不可变字段(如 id、timestamp)或预定义枚举值来构造稳定顺序。

















