Fluent Python 笔记 第 13 章 正确重载运算符

news2024/11/25 6:48:52

运算符重载的作用是让用户定义的对象使用中缀运算符(如 + 和 |)或一元运算符(如 - 和 ~)。说得宽泛一些,在 Python 中,函数调用(())、属性访问(.)和元素访问 / 切片 ([])也是运算符,不过本章只讨论一元运算符和中缀运算符。

13.1 运算符重载基础

Python 中的限制:

  • 不能重载内置类型的运算符
  • 不能新建运算符,只能重载现有的
  • 某些运算符不能重载:is、and、or 和 not(不过位运算符 &、| 和 ~ 可以)

13.2 一元运算符

要遵守运算符的一个基本规则:始终返回一个 新对象。也就是说,不能修改 self,要创建并返回合适类型的新实例。

-(__neg__)

一元取负算术运算符。如果 x 是 -2,那么 -x == 2。

+(__pos__)

一元取正算术运算符。通常,x == +x,但也有一些例外。如果好奇,请阅读“x和+x何时不相等”附注栏。

~(__invert__)

对整数按位取反,定义为 ~x == -(x+1)。如果 x 是 2,那么 ~x == -3。

x 和 +x 何时不相等

第一例与 decimal.Decimal 类有关。如果 x 是 Decimal 实例,在算术运算的上下文中创建,然后在不同的上下文中计算 +x。

ctx = decimal.getcontext()
ctx.prec = 40
one_third = decimal.Decimal('1') / decimal.Decimal('3')
ctx.prec = 28
one_third == +one_third  # False

第二例在collections.Counter的文档中,Counter 相加时,负值和零值计数会从结果中剔除。而一元运算符 + 等同于加上一个空 Counter,因此它产生一个新的 Counter 且仅保留大于零的计数器。

ct['r'] = -3
ct['d'] = 0
>>> ct
Counter({'a': 5, 'b': 2, 'c': 1, 'd': 0, 'r': -3})
>>> +ct
Counter({'a': 5, 'b': 2, 'c': 1})

13.3 重载向量加法运算符+

def __add__(self, other):  # 用下面的版本
    pairs = itertools.zip_longest(self, other, fillvalue=0.0)
    return Vector(a + b for a, b in pairs)  # 返回一个新 Vector 实例

v1 + (10, 20, 30)

a+b:

a.__add__(b) 再尝试 b.__radd__(a)

def __radd__(self, other):
    return self + other

0

别把 NotImplemented 和 NotImplementedError 搞混了。前者是特殊的单例值, 如果中缀运算符特殊方法不能处理给定的操作数,那么要把它返回(return) 给解释器。而 NotImplementedError 是一种异常,抽象类中的占位方法把它抛出(raise),提醒子类必须覆盖。

如果由于类型不兼容而导致运算符特殊方法无法返回有效的结果,那么应该返回 NotImplemented,而不是抛出 TypeError。返回 NotImplemented 时,另一个操作数所属的类型还有机会执行运算,即 Python 会尝试调用反向方法。

 def __add__(self, other):
    try:
        pairs = itertools.zip_longest(self, other, fillvalue=0.0)
        return Vector(a + b for a, b in pairs)
    except TypeError:
        return NotImplemented

13.4 重载标量乘法运算符*

def __mul__(self, scalar):
    if isinstance(scalar, numbers.Real):
        return Vector(n * scalar for n in self)
    else:
        return NotImplemented
def __rmul__(self, scalar):
    return self * scalar

在这里插入图片描述

2

13.5 众多比较运算符

在这里插入图片描述

def __eq__(self, other):
    if isinstance(other, Vector):
        return (len(self) == len(other) and all(a == b for a, b in zip(self, other)))
    else:
        return NotImplemented

那么 != 运算符呢?我们不用实现它,因为从 object 继承的 __ne__ 方法的后备行为满足了 我们的需求:定义了 __eq__ 方法,而且它不返回 NotImplemented,__ne__ 会对 __eq__ 返 回的结果取反。

13.6 增量赋值运算符

如果一个类没有实现表13-1列出的就地运算符,增量赋值运算符只是语法糖:a += b的 作用与 a = a + b 完全一样。对不可变类型来说,这是预期的行为,而且,如果定义了 __add__ 方法的话,不用编写额外的代码,+= 就能使用。
然而,如果实现了就地运算符方法,例如 __iadd__,计算 a += b 的结果时会调用就地运算 符方法。这种运算符的名称表明,它们会就地修改左操作数,而不会创建新对象作为结果。

class AddableBingoCage(BingoCage):
    def __add__(self, other):
        if isinstance(other, Tombola):
            return AddableBingoCage(self.inspect() + other.inspect())
        else:
            return NotImplemented
    def __iadd__(self, other):
        if isinstance(other, Tombola):
            other_iterable = other.inspect()
        else:
            try:
                other_iterable = iter(other)
            except TypeError:
                self_cls = type(self).__name__
                msg = "right operand in += must be {!r} or an iterable"
                raise TypeError(msg.format(self_cls))
        self.load(other_iterable)
        return self  # 增量赋值特殊方法必须返回 self。

一般来说,如果中缀运算符的正向方法(如 __mul__)只处理与 self 属于同 一类型的操作数,那就无需实现对应的反向方法(如 __rmul__),因为按照 定义,反向方法是为了处理类型不同的操作数。

![6](https://github.com/zhangchaosd/superchao/raw/master/_posts/assets/20230212/6.png)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/346265.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Tomcat安装、IDEA发布web项目及通过浏览器访问servlet程序

tomcat安装 在官网上下载tomcat安装包,推荐下载8.5版本 解压安装到任意磁盘,记住安装时的目录 在系统里找到高级系统设置——高级——环境变量——系统变量里的path——编辑——新建,内容填写tomcat中的bin路径的绝对路径。 在bin文件夹找…

【3D目标检测】Pseudo-Stereo for Monocular 3D Object Detection in Autonomous Driving

目录概述细节背景与整体流程图像级别生成特征级别生成损失函数学习深度感知的特征概述 本文是基于单目图像的3D目标检测方法。 【2021】【MonoDLE】 研究的问题: 能否借助立体图像检测算法提高单目图像检测的效果如何实现右侧图像的生成 解决的方法: 受启发于伪…

java基于springboot+vue微信小程序的学生健康管理

任何系统都要遵循系统设计的基本流程,本系统也不例外,同样需要经过市场调研,需求分析,概要设计,详细设计,编码,测试这些步骤,基于Java语言、微信小程序技术设计并实现了学生健康管理小程序。系统主要包括系统首页、个人中心、学生管理、健康档案管理、体检报告管理、健康评估管…

案例分享 | 某券商利用AI技术进行告警关联分析(上)

本内容来自公众号“布博士”------(擎创科技资深产品专家)背景:作为大型券商企业之一,某券商对深入数字化转型,以及对应用、网络、主机、操作系统、中间件、用户使用体验等的全面可观测性要求越来越强烈。由于可观测性…

机器学习在预测脊髓型颈椎病中的应用:一项28名参与者的事后初步研究

机器学习在预测脊髓型颈椎病中的应用:一项28名参与者的事后初步研究 Machine Learning for the Prediction of Cervical Spondylotic Myelopathy: A Post Hoc Pilot Study of 28 Participants 简单说:训练了两个模型:1)预测脊髓型颈椎病诊断&#xff0…

音乐 APP 用户争夺战,火山引擎 VeDI 助力用户体验升级!

更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,并进入官方交流群 国内数字音乐市场正在保持稳定增长。 根据华经产业研究院数据报告显示,2020 年数字音乐市场规模为 357.3 亿元,到 2022 年市场规模已增长至 482.7 …

2月编程语言排行榜新鲜出炉,谁又摘得桂冠?

近日,TIOBE公布了2023年2月编程语言排行榜,本月各个语言表现如何?谁又摘得桂冠?一起来看看吧! TIOBE 2月Top15编程语言: 详细榜单查看TIOBE官网 https://www.tiobe.com/tiobe-index/ 关注IT行业的小伙伴…

LabVIEW中的软件定时应用可以达到怎样的精度

LabVIEW中的软件定时应用可以达到怎样的精度有一个基于软件定时的数据采集应用。采集任务在一个循环结构中完成,使用LabVIEW的定时函数。每次循环间的间隔应该是一个常量,但没有得到优于1ms的定时分辨率。解答:LabVIEW 或LabWindows/CVI定时函数使用的是…

PHP如何实现HTTP服务器

一般来讲,PHP很少谈到“实现HTTP服务”的说法,因为从早期的CGI到后来的PHP-FPM,官方已经给出了最稳定的HTTP解决方案,你只要配合一个Apache或Nginx类的服务器就能实现稳定的HTTP服务。 但PHP并非不能实现HTTP服务,一般…

知识付费小程序怎么做_分享知识付费小程序的作用

在线知识付费产业的主要业务逻辑是基于用户的主动学习需求,为其提供以跨领域基础知识与技能为核心的在线知识服务,提升其达到求知目的的效率。公众号和小程序的迅速发展,又为知识付费提供了技术支持,从而促进了行业的进一步发展。…

UE 虚幻引擎 【DT Subsystem】 插件说明

在虚幻中自带有子系统,可能实现自动实例化。 但是子系统只能在C中继承实现,本插件的目的则是可以直接在蓝图中创建并使用子系统。 官方子系统说明参考: 虚幻引擎编程子系统 | 虚幻引擎5.1文档 (unrealengine.com)https://docs.unrealengine…

Studio 3T 2023.1.1 (macOS, Linux, Windows) - MongoDB 的专业 GUI、IDE 和 客户端

The professional GUI, IDE and client for MongoDB 请访问原文链接:https://sysin.org/blog/studio-3t-2023/,查看最新版。原创作品,转载请保留出处。 作者主页:www.sysin.org Studio 3T,MongoDB 的专业 GUI、IDE 和…

桌面电脑如何快速体验DataEase?

DataEase是一款人人可用的数据可视化分析工具,致力于帮助用户快速分析数据并洞察业务趋势,从而实现业务的改进与优化。但有一些用户提出,目前大部分的部署场景都是将DataEase部署在服务器中,自己只有一台桌面电脑,是不…

初始C++(五):

文章目录一.auto关键字1.1auto关键字用法1.2auto关键字的小细节1.3h获取变量类型二.范围for(语法糖)三.nullptr和NULL一.auto关键字 1.1auto关键字用法 auto这个关键字其实非常简单,用处就是能自动帮你去匹配类型,像下面这段代码: int mai…

Jetpack技术Hilt【实现解耦 】

Hilt是什么? Hilt 是基于 Dagger2 的针对 Android场景定制化 的框架。 这有点像什么? RxAndroid 是 RxJava 的Android平台定制化扩展。Andorid虽然由Java、Kotlin构成,但是它有很多平台的特性,比如它有 Java开发 所不知道的 Cont…

嵌入式开发:AI和Chat GPT改变嵌入式系统的3种方式

嵌入式软件开发是一个已经发展了很多年的领域,它已经见证了许多技术进步。然而,ChatGPT和其他人工智能技术的引入将以前所未有的方式彻底改变该领域。在这篇博文中,我们将探索ChatGPT和AI将改变嵌入式开发的三种方式。方式1 —— CHATGPT/AI自…

Redis之搭建一主多从

搭建redis一主多从的过程 1.在相应位置创建一个文件夹存放redis配置文件 mkdir myredis2.复制redis配置文件到此文件夹中 cp /opt/redis/redis/bin/redis.conf /opt/myredis/redis.conf3.新建三个配置文件 touch redis6379.conf touch redis6380.conf touch redis6381.conf4…

测试开发之Django实战示例 第九章 扩展商店功能

第九章 扩展商店功能在上一章里,为电商站点集成了支付功能,然后可以生成PDF发票发送给用户。在本章,我们将为商店添加优惠码功能。此外,还会学习国际化和本地化的设置和建立一个推荐商品的系统。本章涵盖如下要点:建立…

基于JAVA+SpringBoot+Vue+ElementUI中学化学实验室耗材管理系统

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取项目下载方式🍅 一、项目背景介绍: 当前,中学…

【js文字大小自适应】原生js实现文字大小自适应(附完整源码)

目录1、先睹为快2、代码实现第一步、搭建页面第二步、设置样式第三步、JS实现字体自适应3、源码直通车(百度云下载)【写在前面】之前写过一个大屏的项目,其中里面最头疼的应该是图片,文字,图表(echarts&…