首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
第 13章 性能测量和大O算法分析
13.1 timeit模块
13.2 cProfile分析器
13.3 大O算法分析
13.4 大O阶
13.4.1 使用书架打比方描述大O阶
13.4.2 大O 测量的是最坏情况
13.5 确定代码的大O 阶
13.5.1 为什么低阶项和系数不重要
13.5.2 大O 分析实例
13.5.3 常见函数调用的大O 阶
13.5.4 一眼看出大O 阶
13.5.5 当n 很小时,大O并不重要,而n通常都很小
第 14章 项目实战
14.1 汉诺塔
14.1.1 汉诺塔输出
14.1.2 汉诺塔源代码
14.1.3 汉诺塔编写代码
14.2 四子棋
14.2.1 四子棋输出
14.2.2 四子棋源代码
14.2.3 四子棋编写代码
第 15章 面向对象编程和类
15.1 拿现实世界打比方:填写表格
15.2 基于类创建对象
15.3 创建一个简单的类——WizCoin
15.3.1 方法__init__()和self
15.3.2 特性
15.3.3 私有特性和私有方法
15.4 函数type()和特性__qualname__
15.5 非OOP 和OOP 的例子:井字棋
15.6 为现实世界设计类是一件难事儿
第 16章 面向对象编程和继承
16.1 继承的原理
16.1.1 重写方法
16.1.2 super()函数
16.1.3 倾向于组合而非继承
16.1.4 继承的缺点
16.2 函数isinstance()和issubclass()
16.3 类方法
16.4 类特性
16.5 静态方法
16.6 何时应该使用类和静态的面向对象特性
16.7 面向对象的行话
16.7.1 封装
16.7.2 多态性
16.8 何时不应该使用继承
16.9 多重继承
16.10 方法解析顺序
第 17章 Python 风格的面向对象编程:属性和魔术方法
17.1 属性
17.1.1 将特性转换为属性
17.1.2 使用setter 验证数据
17.1.3 只读属性
17.1.4 什么时候应该使用属性
17.2 Python 的魔术方法
17.2.1 字符串表示魔术方法
17.2.2 数值魔术方法
17.2.3 反射数值魔术方法
17.2.4 原地魔术方法
17.2.5 比较魔术方法
当前位置:
首页>>
技术小册>>
Python编程轻松进阶(五)
小册名称:Python编程轻松进阶(五)
### 17.2.5 比较魔术方法 在Python的面向对象编程中,魔术方法(也称为特殊方法或双下方法)是一组被双下划线包围的方法名,如`__init__`、`__str__`等。它们为Python类提供了丰富的内置功能,使得对象的行为能够自动适应Python的许多内置操作,如比较、迭代、属性访问等。本章将深入探讨比较魔术方法,这些方法使得Python对象能够参与到比较运算符(如`==`、`!=`、`<`、`<=`、`>`、`>=`)的运算中,从而实现对象之间的有序或无序比较。 #### 1. 比较魔术方法概览 比较魔术方法主要包括以下几类: - **等值比较**:`__eq__(self, other)` 和 `__ne__(self, other)` - `__eq__`:定义当使用等号`==`比较两个对象时是否相等。 - `__ne__`:定义当使用不等号`!=`比较两个对象时是否不相等。通常,如果不实现`__ne__`,Python会默认使用`__eq__`的结果取反作为`__ne__`的结果。 - **排序比较**:`__lt__(self, other)`、`__le__(self, other)`、`__gt__(self, other)`、`__ge__(self, other)` - `__lt__`:定义小于(`<`)操作。 - `__le__`:定义小于等于(`<=`)操作。 - `__gt__`:定义大于(`>`)操作。 - `__ge__`:定义大于等于(`>=`)操作。 这些魔术方法的实现决定了对象在比较操作中的行为,使得自定义类型能够像内置类型一样被排序、去重等。 #### 2. 实现等值比较 等值比较是最基础也是最常见的比较类型。通过实现`__eq__`和(可选的)`__ne__`方法,我们可以定义两个对象何时被视为相等。 ```python class Point: def __init__(self, x, y): self.x = x self.y = y def __eq__(self, other): if not isinstance(other, Point): return NotImplemented # 允许其他类型定义如何与Point比较 return self.x == other.x and self.y == other.y def __ne__(self, other): # 可以省略,Python会使用__eq__的结果取反 return not self.__eq__(other) p1 = Point(1, 2) p2 = Point(1, 2) p3 = Point(2, 1) print(p1 == p2) # True print(p1 == p3) # False print(p1 != p3) # True ``` 注意,当比较的两个对象类型不同时,`__eq__`方法应返回`NotImplemented`而不是`False`或抛出异常。这样做可以允许其他类型定义如何与你的类进行比较,体现了Python的“鸭子类型”原则。 #### 3. 实现排序比较 排序比较方法允许你的对象被排序或用作集合(如set)的元素,因为集合和排序操作需要知道对象之间的相对顺序。 ```python class Student: def __init__(self, name, score): self.name = name self.score = score def __lt__(self, other): if not isinstance(other, Student): return NotImplemented return self.score < other.score # 其余排序方法可以根据需要实现,或者通过__lt__推导 students = [Student('Alice', 90), Student('Bob', 85), Student('Charlie', 95)] students.sort() # 默认按score升序排序 print([(s.name, s.score) for s in students]) # 输出可能因实现细节而异,但基本按score排序 ``` 在上面的例子中,我们仅实现了`__lt__`方法,这足以让`Student`对象在`list.sort()`和`sorted()`函数中按分数排序。然而,在实际应用中,如果排序逻辑较为复杂,可能需要同时实现多个排序比较方法以确保所有比较操作的一致性和预期行为。 #### 4. 注意事项 - **一致性**:等值比较(`__eq__`和`__ne__`)必须保证一致性,即如果`a == b`为真,那么在任何时间点`a != b`必须为假,反之亦然。同样,排序比较方法(`__lt__`、`__le__`、`__gt__`、`__ge__`)之间也必须保持逻辑上的一致性。 - **类型检查**:在比较魔术方法中,经常需要检查`other`对象的类型。虽然Python是动态类型语言,但适当的类型检查可以避免意外的行为或错误。 - **性能考虑**:比较操作可能非常频繁,特别是在使用集合或进行大量排序时。因此,比较魔术方法的实现应尽量高效,避免不必要的计算或资源消耗。 - **反射与传递性**:在实现排序比较方法时,要注意它们之间的反射性和传递性。例如,如果`a < b`为真且`b < c`为真,那么`a < c`也应该为真。 - **使用`functools.total_ordering`**:如果你的类只需要支持等值比较和一种排序比较(如仅实现了`__lt__`),可以使用`functools.total_ordering`装饰器来自动生成其他缺失的排序比较方法,从而简化代码并减少出错的可能性。 #### 5. 结论 比较魔术方法是Python面向对象编程中一个强大而灵活的特性,它们允许你定义对象之间的比较逻辑,使得自定义类型能够无缝地参与到Python的排序、去重等操作中。通过恰当地实现这些魔术方法,你可以创建出既符合直觉又功能强大的Python类。然而,也需要注意它们之间的逻辑一致性、性能考虑以及类型检查等问题,以确保你的类能够正确地参与到Python的内置操作中。
上一篇:
17.2.4 原地魔术方法
该分类下的相关小册推荐:
Python甚础Django与爬虫
Python合辑4-130个字符串操作示例
Python数据分析与挖掘实战(上)
Python3网络爬虫开发实战(上)
Python3网络爬虫开发实战(下)
Python机器学习实战
Python高并发编程与实战
Python自动化办公实战
实战Python网络爬虫
Python面试指南
Python编程轻松进阶(四)
Python机器学习基础教程(上)