苦练Python第54天:比较运算魔术方法全解析,让你的对象“懂大小、能排序”!

前言

大家好,我是 倔强青铜三 。欢迎关注我,微信公众号:倔强青铜三。欢迎点赞、收藏、关注,一键三连!

欢迎来到 苦练Python第54天

今天咱们要深入探索Python类中的 比较运算魔术方法,这可是让你的对象**"懂大小、能排序"**的关键所在!

这些魔术方法包括:__lt____le____eq____ne____gt____ge____hash__

一口气吃透它们,你的类就能在比较、排序、集合操作中如鱼得水!


比较运算魔术方法全家福

方法 触发场景 作用
__lt__ a < b 小于
__le__ a <= b 小于等于
__eq__ a == b 等于
__ne__ a != b 不等于
__gt__ a > b 大于
__ge__ a >= b 大于等于
__hash__ hash(a) 计算对象的哈希值

__lt__:小于操作

作用

定义对象的"小于"逻辑,用于比较两个对象的大小。

触发场景

当你写下 a < b 时,Python会调用 a.__lt__(b)

示例

python 复制代码
class Student:
    def __init__(self, name, score):
        self.name = name
        self.score = score

    def __lt__(self, other):
        """触发场景:s1 < s2"""
        print("__lt__ 被调用!")
        return self.score < other.score

s1 = Student("张三", 85)
s2 = Student("李四", 90)
print(s1 < s2)  # __lt__ 被调用! -> True

__le__:小于等于操作

作用

定义对象的"小于等于"逻辑。

触发场景

当你写下 a <= b 时,Python会调用 a.__le__(b)

示例

python 复制代码
class Student:
    ...
    def __le__(self, other):
        """触发场景:s1 <= s2"""
        print("__le__ 被调用!")
        return self.score <= other.score

print(s1 <= s2)  # __le__ 被调用! -> True

__eq__:等于操作

作用

定义对象的"等于"逻辑,默认比较内存地址,但可以通过这个方法自定义。

触发场景

当你写下 a == b 时,Python会调用 a.__eq__(b)

示例

python 复制代码
class Student:
    ...
    def __eq__(self, other):
        """触发场景:s1 == s2"""
        print("__eq__ 被调用!")
        return self.score == other.score

print(s1 == s2)  # __eq__ 被调用! -> False

__ne__:不等于操作

作用

定义对象的"不等于"逻辑。

触发场景

当你写下 a != b 时,Python会调用 a.__ne__(b)

示例

python 复制代码
class Student:
    ...
    def __ne__(self, other):
        """触发场景:s1 != s2"""
        print("__ne__ 被调用!")
        return not self.__eq__(other)

print(s1 != s2)  # __ne__ 被调用! -> True

__gt__:大于操作

作用

定义对象的"大于"逻辑。

触发场景

当你写下 a > b 时,Python会调用 a.__gt__(b)

示例

python 复制代码
class Student:
    ...
    def __gt__(self, other):
        """触发场景:s1 > s2"""
        print("__gt__ 被调用!")
        return self.score > other.score

print(s1 > s2)  # __gt__ 被调用! -> False

__ge__:大于等于操作

作用

定义对象的"大于等于"逻辑。

触发场景

当你写下 a >= b 时,Python会调用 a.__ge__(b)

示例

python 复制代码
class Student:
    ...
    def __ge__(self, other):
        """触发场景:s1 >= s2"""
        print("__ge__ 被调用!")
        return self.score >= other.score

print(s1 >= s2)  # __ge__ 被调用! -> False

__hash__:哈希值计算

作用

定义对象的哈希值,用于集合操作(如 setdict)。

触发场景

当你调用 hash(a) 或将对象放入集合时,Python会调用 a.__hash__()

示例

python 复制代码
class Student:
    ...
    def __hash__(self):
        """触发场景:hash(s1) 或 s1 放入集合"""
        print("__hash__ 被调用!")
        return hash(self.score)

print(hash(s1))  # __hash__ 被调用!
students = {s1, s2}  # __hash__ 被调用!

"一键补齐比较运算符" 的装饰器

在 Python 中写一个可排序的类,需要实现 __eq____lt____le____gt____ge____ne__,样板代码量大且易错。

functools.total_ordering 就是官方给出的"懒癌"解决方案,它是一个 "一键补齐比较运算符" 的装饰器。

装饰器 @total_ordering自动生成缺失的比较方法

前提:你已提供 __eq__ 以及 __lt____le____gt____ge__ 中的任意 一个 。生成的代码逻辑严谨,避免手写 NotImplemented 处理。

使用方法

  1. 导入:from functools import total_ordering
  2. 装饰类:@total_ordering
  3. 实现 __eq__ 和一个顺序方法即可。

示例:学生成绩排序

python 复制代码
from functools import total_ordering

@total_ordering
class Student:
    def __init__(self, name, score):
        self.name, self.score = name, score

    def __eq__(self, other):
        return self.score == other.score

    def __lt__(self, other):
        return self.score < other.score

# 使用
alice, bob = Student('Alice', 90), Student('Bob', 85)
print(alice > bob)   # True
print(bob <= alice)  # True
print(sorted([bob, alice]))  # [Bob, Alice]

踩坑提示

  • 必须实现 __eq__,否则抛 ValueError
  • 不要混用 __cmp__(Python 3 已移除)。
  • 同时给出多个顺序方法时,装饰器以最左边为准。

实战:打造可比较、可排序的"分数"类

python 复制代码
from functools import total_ordering

@total_ordering
class Score:
    def __init__(self, value):
        self.value = value

    def __eq__(self, other):
        return self.value == other.value

    def __lt__(self, other):
        return self.value < other.value

    def __hash__(self):
        return hash(self.value)

    def __repr__(self):
        return f"Score({self.value})"

# 测试
s1 = Score(85)
s2 = Score(90)
s3 = Score(85)

print(s1 < s2)   # True
print(s1 == s3)  # True
print(s1 != s2)  # True
print(s1 > s2)   # False
print(s1 >= s3)  # True

scores = {s1, s2, s3}
print(scores)  # {Score(85), Score(90)}

sorted_scores = sorted([s1, s2, s3])
print(sorted_scores)  # [Score(85), Score(90)]

小结

  • 比较运算魔术方法 让对象支持 < <= == != > >= 比较。
  • __hash__ 是集合操作的关键,必须与 __eq__ 保持一致。
  • 使用 functools.total_ordering 可以简化比较方法的实现。

动手挑战

    1. 实现一个 Person 类,支持按年龄比较大小,并且可以放入集合。
    1. 创建一个 Book 类,支持按书名排序,并且可以通过 hash() 获取哈希值。
    1. 进阶:让 Book 类支持按书名和作者同时比较大小。

互动时间

你最常用哪个比较魔术方法?

A. __eq__(比较狂魔)

B. __lt__(排序狂魔)

C. __hash__(集合狂魔)

评论区告诉我你的答案 + 骚操作!

最后感谢阅读!欢迎关注我,微信公众号倔强青铜三

一键三连(点赞、收藏、关注)!

相关推荐
科技苑2 小时前
Python 图像处理技巧指南
python
倔强青铜三2 小时前
苦练Python第53天:数值运算魔术方法从入门到精通
人工智能·python·面试
Q_Q5110082852 小时前
python+springboot+uniapp基于微信小程序的停车场管理系统 弹窗提示和车牌识别
vue.js·spring boot·python·django·flask·uni-app·node.js
yaso_zhang3 小时前
jetpack6.1 的新 pytorch 2.5.1 版本在哪里?下载中心仅提供 pytorch v2.5.0a0。
人工智能·pytorch·python
金井PRATHAMA3 小时前
语义三角论对人工智能自然语言处理深层语义分析的影响与启示
人工智能·自然语言处理·知识图谱
Canace3 小时前
我们是否需要AI知识库
人工智能·aigc·ai编程
en-route3 小时前
从零开始学神经网络——前馈神经网络
人工智能·深度学习·神经网络
前端伪大叔3 小时前
第13篇:🎯 如何精准控制买入卖出价格?entry/exit\_pricing 实战配置
javascript·python
城南皮卡丘3 小时前
基于YOLO8+flask+layui的行人跌倒行为检测系统【源码+模型+数据集】
python·flask·layui