zoukankan      html  css  js  c++  java
  • 《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 的 结果时会调用就地运算符方法。这种运算符的名称表明,它们会就地修 改左操作数,而不会创建新对象作为结果。

    你不逼自己一把,你永远都不知道自己有多优秀!只有经历了一些事,你才会懂得好好珍惜眼前的时光!
  • 相关阅读:
    SpringBoot 整合Redis
    IDEA 修改之前保存的git地址的账号和密码
    SpringBoot 上传文件功能
    JAVA结合 JSON Web Token(JWT) 工具类
    SpringBoot 整合Spring Security框架
    Sublime Text3 设置
    Python 正则表达式
    Django+uWSGI+Nginx 部署网站
    web 设计中引入字体
    HTML 超链接返回上一级
  • 原文地址:https://www.cnblogs.com/zhazhaacmer/p/14463095.html
Copyright © 2011-2022 走看看