🧩 第四章 面向对象编程技术:去除冗余、进行整理
📄 一句话概括

类不只是模板,它同时是一个类型——isinstance 算子类,type is 不算。

📝 本节和前面几节的关系

4.11 讲类型嵌在哪儿,这一节讲类这个类型怎么拿来用。

一、两个判断

isinstance(Dog(), Animal) → True isinstance(Cat(), Dog) → False(猫不是狗) type(Dog()) is Dog → True,type(Dog()) is Animal → False 同样是【判断类型】,一个算上了子类,一个没有。

二、差别在哪

isinstance(x, A):看 x 是不是 A 或 A 的子类——子类算。 type(x) is A:看 x 的类型是不是正好是 A——子类不算。 写多态代码要用 isinstance,判等要用 type is。 用错了会出现子类明明能用却被挡掉这种事——这种 bug 最难查,因为代码看着合理。

三、为什么这条重要

类一旦是类型,它就能出现在变量声明、参数、返回值里。 于是【设计】可以写成【类型关系】——谁是谁的子类、谁实现了谁的接口。 而类型关系能被工具检查:静态检查、IDE 跳转、重构重命名,全都靠它。 这就是为什么第 8 章要讲 UML、第 10 章要讲设计——它们画的都是类型关系。

四、一个提醒

别用 type 判断来做多态分发。那就是 4.8 说的 if 分支版,加一种类型要改调用端。 真正该做的是让对象自己响应,而不是在调用方判断它是什么。 判断类型只该出现在两个地方:入口校验和边界转换。

五、动手 Demo:将类作为类型使用

Dog 继承 Animal,拿两个判断各试一次。 看子类在两种判断下的结果是不是一样。

class Animal: pass
class Dog(Animal): pass
class Cat(Animal): pass

d = Dog()
print(isinstance(d, Animal))   # 子类算
print(type(d) is Animal)       # 子类不算
print(type(d) is Dog)

实跑输出:

--------------------------------------------------------------------
将类作为类型使用
--------------------------------------------------------------------

  类不只是【模板】,**它同时是一个类型**——可以拿来做检查。

      isinstance(Dog(), Animal) → True
      isinstance(Cat(), Dog)    → False
      type(Dog()) is Dog        → True
      type(Dog()) is Animal     → False

  实测这两个判断的差别很关键:

  判断                 看什么                   子类算吗
  -------------------------------------------------------
  isinstance(x, A)     是不是 A 或 A 的子类     算
  type(x) is A         类型是不是正好是 A       不算

  **写多态代码时要 `isinstance`,判等时要 `type is`。**
  用错了就会出现【子类明明能用却被挡掉】这种怪事。

  这一条还有一层意义:**类一旦是类型,它就能出现在变量声明、参数、返回值里。**
  **于是【设计】可以写成【类型关系】,而类型关系能被工具检查。**

实测:isinstance 算子类(True),type is 不算(False)。 写多态代码用 isinstance,判等用 type is——用错了会出现子类被挡掉的怪事。

30 秒实验

  1. 把一个用 type 做多态分发的函数改成让对象自己响应,看调用端少了几行。
  2. 查一查你的语言里 isinstance 的等价物叫什么。

常见误区

  1. 以为类是模板,不是类型。它同时是类型,能出现在声明和参数里。
  2. 以为两个判断等价。一个算子类,一个不算子类。
自测三问(点开对答案) 1. `isinstance` 和 `type is` 差在哪? —— `isinstance` 看是不是 A 或 A 的子类(子类算);`type is` 看类型是不是正好 A(子类不算)。 2. 什么时候用哪个? —— 写多态代码用 `isinstance`(子类要能通过);判等或精确匹配用 `type is`。 3. 类作为类型有什么意义? —— 它能出现在变量声明、参数、返回值里,于是设计可以写成类型关系,并被工具检查。

相关笔记