最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如何在Python中实现支持数学运算的自定义类
时间:2026-06-24 08:26:46 编辑:袖梨 来源:一聚教程网
__add__ 没生效是因为未实现该魔术方法或返回值错误;Python 中自定义类必须显式定义 __add__(及 __radd__)并返回新实例,否则报 TypeError。
为什么 __add__ 没生效,加号还是报错?
Python 中自定义类默认不支持 + 运算,直接调用会抛出 TypeError: unsupported operand type(s)。必须显式实现对应双下划线方法(即“魔术方法”),且返回值类型需合理——比如 __add__ 应返回同类实例或兼容类型,不能只写 print 或返回 None。
常见错误包括:忘记 return、返回原始数值而非新实例、未处理右操作数类型(如 int + MyNumber 场景)。
- 若希望支持
a + b,必须实现__add__(self, other) - 若希望支持
5 + a(即 int 在左),还需实现__radd__(self, other),否则触发NotImplemented后回退失败 - 返回新实例而非修改
self,保持不可变语义更安全(除非你明确设计为可变)
如何让 == 和 print() 表现符合直觉?
不实现 __eq__ 时,== 默认比较对象身份(id()),两个值相同的实例也会返回 False;不实现 __str__ 或 __repr__,print() 只显示内存地址。
建议优先实现 __eq__ 和 __repr__:__repr__ 应尽量返回可复现对象的字符串(如 MyNumber(3.14)),__str__ 可用于更友好的显示(如 "3.14")。
立即学习“Python免费学习笔记(深入)”;
-
__eq__(self, other)中需先判断other类型是否兼容,避免AttributeError - 若重写了
__eq__,强烈建议同时实现__hash__(除非对象可变),否则无法放入set或作字典键 - 不要在
__eq__中用isinstance(other, self.__class__)判类型——它不支持子类;改用hasattr(other, 'value')或白名单检查更稳妥
支持 abs()、round() 和比较运算需要哪些方法?
数学内置函数和比较操作符各自绑定特定方法:abs(a) 调用 a.__abs__(),round(a) 调用 a.__round__(),而 、<code>> 等则对应 __lt__、__gt__ 等。Python 不会自动推导它们,缺一个就报错。
注意:__lt__ 和 __gt__ 并不互推——实现 __lt__ 不代表 > 自动可用;但可借助 functools.total_ordering 装饰器,只写 __eq__ 和一个比较方法(如 __lt__),其余自动补全。
-
__abs__应返回绝对值对应的新实例,不是原地修改 -
__round__(self, ndigits=None)的ndigits参数必须支持None(即无参数调用round(a)) - 比较方法返回
True/False,**不能**返回1/0或其他值,否则逻辑错乱
浮点精度、类型混合与性能容易被忽略的细节
当你的类包装浮点数时,__add__ 直接用 self.value + other.value 会继承 float 的精度问题;若支持与 int、float 混合运算,需在方法内做类型归一化,否则 MyNumber(2) + 3.5 可能失败。
性能上,每个运算都新建实例会有开销。若频繁计算(如科学计算场景),可考虑缓存或提供就地运算方法(如 __iadd__),但需明确文档说明其可变性。
- 在
__add__中用isinstance(other, (int, float))分支处理内置数值类型,再转为统一内部表示 - 避免在
__eq__或__hash__中调用高开销计算(如字符串格式化),否则影响字典查找性能 - 如果类可能被 pickle,确保所有参与运算的属性都可序列化,且
__init__参数能覆盖核心状态
相关文章
- Premiere怎样制作延时摄影效果 07-04
- 龙虾机器人能不能画画 07-04
- MP3剪切合并大师怎么剪切音乐 07-04
- 明日方舟终末地物资调度指南|终末地模式资源获取与高效分配策略 07-04
- 如何用imovie从视频中提取音频 07-04
- 如何使用webstorm实现javascript的Debug调试功能 07-04