当前位置:首页>python>Python functools.total_ordering 搞定类的比较

Python functools.total_ordering 搞定类的比较

  • 2026-09-10 20:07:43
Python functools.total_ordering 搞定类的比较
在我们日常的python应用时,经常会自定义类,比如定义一个任务状态、枚举类型,如果想让这些类的实例支持大小比较,例如<、>等,正常情况下需要手动实现比较运算符的方法,不仅繁琐,还容易遗漏写错。
而functools.total_ordering就是来解决这个痛点,它是一个装饰器,能自动帮我们不全比较运算符,只需要手动实现其中一个和相等判断方法,就能让自定义类支持完整的比较操作。让我们看看官方定义:
使用 total_ordering 装饰器的类,必须满足两个条件:​1. 必须定义以下 4 个方法中的任意 1 个:__lt__()(小于)、__le__()(小于等于)、__gt__()(大于)、__ge__()(大于等于);​2. 同时,类必须提供 __eq__() 方法(用于判断相等)。
简单的说,写两个方法,装饰器会补全剩下4个。接下来我们铜鼓实例,结合Enum枚举类,用total_ordering实现美剧值的大小比较,我们看看代码:
from enum import Enum, auto  # 导入枚举相关模块from functools import total_ordering  # 导入total_ordering装饰器# 用total_ordering装饰自定义枚举类@total_orderingclass LifeCycle(Enum):    # 定义枚举值,auto()会自动分配递增的整数(0、1、2...)    configure = auto()    # 配置阶段    glob = auto()         # 全局处理阶段    load = auto()         # 加载阶段    pre_render = auto()   # 预渲染阶段    render = auto()       # 渲染阶段    post_render = auto()  # 后渲染阶段    save = auto()         # 保存阶段    # 手动实现__lt__()方法(小于),这是我们选的1个核心比较方法    def __lt__(self, other):        try:            # 比较两个枚举实例的value值(auto()分配的整数)            return self.value < other.value        except AttributeError:            # 兼容:如果other不是枚举实例,直接用自身value和other比较            return self.value < other    # 手动实现__eq__()方法(相等判断),必须提供    def __eq__(self, other):        try:            # 比较两个枚举实例的value值            return self.value == other.value        except AttributeError:            # 兼容:如果other不是枚举实例,直接用自身value和other比较            return self.value == otherv
上面的代码中,我们只手动实现了__lt__()和__eq__()两个方法,但是加上@total_ordering装饰器后,python会自动帮我们实现下面的4个方法:
__le__():小于等于(基于 __lt__ 和 __eq__ 推导)__gt__():大于(基于 __lt__ 取反推导)__ge__():大于等于(基于 __gt__ 和 __eq__ 推导)__ne__():不等于(基于 __eq__ 取反推导)
代码中使用了try-except捕获AttributeError,为的是兼容两种比较场景:1.两个LifeCycle枚举实例比较;2.枚举实例和整数比较。实际运行效果如下:
# 测试两个枚举实例比较print(LifeCycle.configure < LifeCycle.render)  # True(0 < 4)print(LifeCycle.save > LifeCycle.pre_render)   # True(6 > 3)print(LifeCycle.load == LifeCycle.load)        # Trueprint(LifeCycle.glob != LifeCycle.configure)   # True# 测试枚举实例和整数比较print(LifeCycle.post_render < 6)  # True(5 < 6)print(LifeCycle.save >= 6)        # True(6 >= 6)
当然在使用时也要注意一些问题,必须实现__eq__()方法,否则会报错,这是装饰器推到其它比较方法的前提,只需要实现4个比较方法中的任意1个即可,如果手动实现了个多个比较方法,装饰器会优先使用手动实现的这些。

最新文章

随机文章