只定义__eq__和__lt__不够,因Python不自动推导>=等操作;未用@total_ordering时,>=等会回退到id比较,!=虽可fallback但其余均不安全;正确做法是@total_ordering+__eq__和一个有序方法(如__lt__)。

直接实现 __eq__ 和 __lt__ 就够用,但想支持所有比较操作(!=、>= 等),必须配合 functools.total_ordering 装饰器,否则会出错或行为不一致。
为什么只写 __eq__ 和 __lt__ 不够
Python 不会自动推导其他比较方法。比如只定义了 __eq__ 和 __lt__,调用 a >= b 会回退到默认的基于对象身份的比较(即 id(a) >= id(b)),结果完全不可控;a != b 虽然能 fallback 到 not a == b,但这是唯一有默认逻辑的,其余(>、<=、>=)全都不安全。
- 没加
@total_ordering时,__ge__、__gt__、__le__都不会被自动生成 - 手动补全全部六个方法极易出错,比如
__ge__写成not self < other比self > other or self == other更可靠,但容易漏边界 - Python 3 明确移除了
__cmp__,不再接受“三态返回值”方案
正确做法:用 @total_ordering + 最小必要方法
只需定义 __eq__ 和**一个**有序关系方法(推荐 __lt__),再加 @total_ordering 装饰器,其余比较都会自动补全且语义正确。
调用 Cutout.Pro 视觉处理 API 进行背景移除、人像抠图和照片增强,支持文件上传与图片 URL 输入。
from functools import total_ordering
@total_ordering
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __eq__(self, other):
if not isinstance(other, Person):
return NotImplemented
return (self.name, self.age) == (other.name, other.age)
def __lt__(self, other):
if not isinstance(other, Person):
return NotImplemented
return (self.name, self.age) < (other.name, other.age)
-
return NotImplemented是关键:让 Python 尝试调用other.__gt__(self)等反向方法,避免TypeError - 元组比较
(self.name, self.age)天然支持字典序,比手写嵌套if更简洁安全 - 装饰器会自动生成
__le__、__gt__、__ge__,且全部基于你写的__lt__和__eq__
常见错误和兼容性注意点
这些坑不踩一次很难意识到:
立即学习“Python免费学习笔记(深入)”;
- 忘记
isinstance检查 → 和不同类实例比较时抛AttributeError,而不是安静返回False或NotImplemented - 返回
False而非NotImplemented→ 导致跨类型比较直接失败,无法触发反向方法 - 在
__eq__中用==比较可能抛异常的字段(如float('nan'))→nan == nan是False,但你可能期望相等性稳定 -
@total_ordering在 Python 2.7+ 和 3.x 都可用,但 Python 2 中若未定义__eq__,会 fallback 到is,而 Python 3 强制要求显式定义
真正麻烦的是跨类型比较的健壮性设计——NotImplemented 的返回时机、字段是否允许为 None、排序键里要不要忽略大小写,这些细节一旦定下来就很难改。

















