返回介绍

13.7 本章小结

发布于 2024-02-05 21:59:47 字数 1229 浏览 0 评论 0 收藏 0

本章首先说明了 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文