__lt__ 是排序最关键的魔法方法,因为 sorted() 和 list.sort() 默认仅依赖它比较对象;只需实现 __lt__ 和 __eq__,配合 @total_ordering 即可自动生成其余比较方法,且需返回 bool、处理 NotImplemented、避免耗时操作。

为什么 __lt__ 是排序最关键的魔法方法
Python 的 sorted() 和 list.sort() 默认只依赖 __lt__(less than)来比较对象。只要实现了它,其他比较(如 sorted()、heapq、min())基本都能工作;而只实现 __eq__ 或 __gt__ 是没用的。
常见错误是试图重载所有六个比较方法——没必要,而且容易漏掉逻辑一致性。CPython 会自动基于 __lt__ 和 __eq__ 推导出其余行为(前提是没显式定义冲突方法)。
- 必须返回
bool,不能返回int(比如 -1/0/1),否则会静默失败或抛TypeError - 如果比较涉及
None或不同类型,应在方法内主动判断并返回NotImplemented(不是NotImplementedError!),让 Python 尝试反向调用 - 避免在
__lt__中做耗时操作(如 IO、数据库查询),排序性能直接受影响
用 @total_ordering 节省重复代码
手动写齐 __lt__、__le__、__gt__、__ge__、__eq__ 容易出错且冗余。functools.total_ordering 装饰器能根据你定义的 __lt__ 和 __eq__ 自动生成其余方法。
注意:必须显式定义 __eq__,否则会回退到默认的内存地址比较,导致逻辑错误。
from functools import total_ordering
<p>@total_ordering
class Person:
def <strong>init</strong>(self, name, age):
self.name = name
self.age = age</p><pre class="brush:php;toolbar:false;">def __lt__(self, other):
if not isinstance(other, Person):
return NotImplemented
return self.age <p></p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill8054" title="python-parallelization"><img
src="https://img.php.cn/upload/skill/000/000/081/179181013081932.jpg" alt="python-parallelization" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill8054" title="python-parallelization" class="overflowclass">python-parallelization</a>
<p class="overflowclass">将顺序 Python 代码转换为并行/并发实现,用于在需要并行化 Python 代码、提升性能时使用。</p>
</div>
<a rel="nofollow" href="/xiazai/skill8054" title="python-parallelization" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>多字段排序时别硬写嵌套逻辑
想先按部门、再按薪资、最后按入职时间排序?直接在 __lt__ 里写三层 if-elif-else 很难维护,也容易漏边界。
更可靠的做法是构造可比较的元组:Python 元组天然支持逐元素比较,语义清晰且高效。
- 升序字段直接放元组里,降序字段加负号(数值)或取反(
not布尔) - 字符串降序可用
name[::-1],但更推荐用key参数替代重载运算符(见下一点) - 元组中任意元素为
None会导致TypeError,需提前转换(如obj.department or '')
key
sorted(employees, key=lambda x: (-x.salary, x.name))- 对不可变对象或第三方类,这是唯一选择
- 需要动态排序条件(如用户选字段)时,
key可配合operator.attrgetter或闭包生成
真正需要重载的典型场景只有:该类的「自然顺序」非常明确且稳定(如日期、坐标、版本号),且会被频繁用于各种容器和算法中。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










