- 前言
- 目标读者
- 非目标读者
- 本书的结构
- 以实践为基础
- 硬件
- 杂谈:个人的一点看法
- Python 术语表
- Python 版本表
- 排版约定
- 使用代码示例
- 第一部分 序幕
- 第 1 章 Python 数据模型
- 第二部分 数据结构
- 第 2 章 序列构成的数组
- 第 3 章 字典和集合
- 第 4 章 文本和字节序列
- 第三部分 把函数视作对象
- 第 5 章 一等函数
- 第 6 章 使用一等函数实现设计模式
- 第 7 章 函数装饰器和闭包
- 第四部分 面向对象惯用法
- 第 8 章 对象引用、可变性和垃圾回收
- 第 9 章 符合 Python 风格的对象
- 第 10 章 序列的修改、散列和切片
- 第 11 章 接口:从协议到抽象基类
- 第 12 章 继承的优缺点
- 第 13 章 正确重载运算符
- 第五部分 控制流程
- 第 14 章 可迭代的对象、迭代器和生成器
- 14.1 Sentence 类第1版:单词序列
- 14.2 可迭代的对象与迭代器的对比
- 14.3 Sentence 类第2版:典型的迭代器
- 14.4 Sentence 类第3版:生成器函数
- 14.5 Sentence 类第4版:惰性实现
- 14.6 Sentence 类第5版:生成器表达式
- 14.7 何时使用生成器表达式
- 14.8 另一个示例:等差数列生成器
- 14.9 标准库中的生成器函数
- 14.10 Python 3.3 中新出现的句法:yield from
- 14.11 可迭代的归约函数
- 14.12 深入分析 iter 函数
- 14.13 案例分析:在数据库转换工具中使用生成器
- 14.14 把生成器当成协程
- 14.15 本章小结
- 14.16 延伸阅读
- 第 15 章 上下文管理器和 else 块
- 第 16 章 协程
- 第 17 章 使用期物处理并发
- 第 18 章 使用 asyncio 包处理并发
- 第六部分 元编程
- 第 19 章 动态属性和特性
- 第 20 章 属性描述符
- 第 21 章 类元编程
- 结语
- 延伸阅读
- 附录 A 辅助脚本
- Python 术语表
- 作者简介
- 关于封面
13.7 本章小结
本章首先说明了 Python 对运算符重载施加的一些限制:禁止重载内置类型的运算符,而且限于重载现有的运算符,不过有几个例外(is、and、or、not)。
随后,本章讲解了如何重载一元运算符,并实现了 __neg__ 和 __pos__ 方法。接着重载中缀运算符,首先是 +,它由 __add__ 方法提供支持。我们得知,一元运算符和中缀运算符的结果应该是新对象,并且绝不能修改操作数。为了支持其他类型,我们返回特殊的 NotImplemented 值(不是异常),让解释器尝试对调操作数,然后调用运算符的反向特殊方法(如 __radd__ )。图 13-1 中的流程图概述了 Python 处理中缀运算符的算法。
如果操作数的类型不同,我们要检测出不能处理的操作数。本章使用两种方式处理这个问题:一种是鸭子类型,直接尝试执行运算,如果有问题,捕获 TypeError 异常;另一种是显式使用 isinstance 测试,__mul__ 方法就是这么做的。这两种方式各有优缺点:鸭子类型更灵活,但是显式检查更能预知结果。如果选择使用 isinstance,要小心,不能测试具体类,而要测试 numbers.Real 抽象基类,例如 isinstance(scalar, numbers.Real)。这在灵活性和安全性之间做了很好的折中,因为当前或未来由用户定义的类型可以声明为抽象基类的真实子类或虚拟子类,详情参见第 11 章。
接下来的话题是众多比较运算符。我们通过 __eq__ 方法实现了 ==,而且发现 Python 在 object 基类中通过 __ne__ 方法为 != 提供了便利的实现。Python 处理这些运算符的方式与 >、<、>= 和 <= 稍有不同,具体而言是选择反向方法的逻辑不同,此外 Python 还会特别处理 == 和 != 的后备机制:从不抛出错误,因为 Python 会比较对象的 ID,作最后一搏。
最后一节专门讨论了增量赋值运算符。我们发现,Python 处理这种运算符的方式是把它们当作常规的运算符加上赋值操作,即 a += b 其实会当成 a = a + b 处理。这样会始终创建新对象,因此可变类型和不可变类型都能用。对可变对象来说,可以实现就地特殊方法,例如支持 += 的 __iadd__ 方法,然后修改左操作数的值。为了举例说明,我们把不可变的 Vector 类放到一边,为 BingoCage 的子类实现了 += 运算符,它会把元素添加到随机选号池中,这与内置的 list 类型把 += 当成 list.extend() 方法的快捷方式类似。在实现的过程中,我们得知在可接受的类型方面,+ 应该比 += 严格。对序列类型来说,+ 通常要求两个操作数属于同一类型,而 += 的右操作数往往可以是任何可迭代对象。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论