《Fluent Python》 CH.13_面向对象_正确重载运算符 (可以重载加减乘除、取反取正、位运算等,部分支持不new对象的就地重载)

小结

  • P551-P589,共计 38页

  • 有些事情让我不安,比如运算符重载。我决定不支持运算符重载, 这完全是个人选择,因为我见过太多 C++ 程序员滥用它。
    ——James Gosling Java 之父

主要内容:

  • Python 如何处理中缀运算符中不同类型的操作数

  • 使用鸭子类型或显式类型检查处理不同类型的操作数

  • 中缀运算符如何表明自己无法处理操作数

  • 众多比较运算符(如 ==、>、<=,等等)的特殊行为

  • 增量赋值运算符(如 +=)的默认处理方式和重载方式

  • 本章速读

1. Java不支持运算符重载,因为Java之父不要这么搞
2. 支持重载取负数/取正数/取反的重载,分别重写对象的__neg__、__pos__和__invert__即可.
3. 处理add和radd(“右向”)的冲突,同时出现的话,先执行左对象的add再执行右对象的radd。
4. 重载乘法: __mul__ 和 __rmul__
5. 就地加法:就地运算符方法,例如 __iadd__。

13.1 运算符重载基础

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

13.2 一元运算符

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

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

~(invert) 对整数按位取反,定义为 ~x == -(x+1)。如果 x 是 2,那么 ~x == -3;如果是对象,在重载后需要返回对应的反集等相似意思。

支持一元运算符很简单,只需实现相应的特殊方法。这些特殊方法只有 一个参数,self。然后,使用符合所在类的逻辑实现。不过,要遵守运 算符的一个基本规则:始终返回一个新对象。也就是说,不能修改 self,要创建并返回合适类型的新实例。

13.3 重载向量加法运算符+

重载.__add__ 方法

处理add和radd(“右向”)的冲突

为了支持涉及不同类型的运算,Python 为中缀运算符特殊方法提供了特 殊的分派机制。对表达式 a + b 来说,解释器会执行以下几步操作:

  • (1) 如果 a 有 add 方法,而且返回值不是 NotImplemented,调用 a.add(b),然后返回结果。
  • (2) 如果 a 没有 add 方法,或者调用 add 方法返回 NotImplemented,检查 b 有没有 radd 方法,如果有,而且没有 返回 NotImplemented,调用 b.radd(a),然后返回结果。
  • (3) 如果 b 没有 radd 方法,或者调用 radd 方法返回 NotImplemented,抛出 TypeError,并在错误消息中指明操作数类型 不支持

13.4 重载标量乘法运算符*

Vector([1, 2, 3]) * x 是什么意思?

如果 x 是数字,就是计算标量 积(scalar product),结果是一个新 Vector 实例,各个分量都会乘以 x——这也叫元素级乘法(elementwise multiplication),使用np.dot()来计算点乘即可。

v1 = list([1, 2, 3])
print(v1 * 10)

[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]

回到标量积的话题。我们依然先实现最简可用的 mulrmul 方法:

# 在Vector类中定义
def __mul__(self, scalar):
    return Vector(n * scalar for n in self)
def __rmul__(self, scalar):
    return self * scalar

13.5 众多比较运算符

对于 __ne__,现在 Python 3 返回结果是对 __eq__ 结果的取反。

13.6 增量赋值运算符

如果定义了 add 方法的话,不用编写额 外的代码,+= 就能使用。

语法糖而已.

如果实现了就地运算符方法,例如 iadd,计算 a += b 的 结果时会调用就地运算符方法。这种运算符的名称表明,它们会就地修 改左操作数,而不会创建新对象作为结果。

你不逼自己一把,你永远都不知道自己有多优秀!只有经历了一些事,你才会懂得好好珍惜眼前的时光!
原文地址:https://www.cnblogs.com/zhazhaacmer/p/14463095.html