🧩 第六章 重用:OOP带来的软件重用和思想重用
📄 一句话概括

认出模式就等于认出了结构——实测 collections.abc 里有 53 个抽象基类,每个都是一块路标。

📝 本节和前面几节的关系

6.9 讲模式是什么,这一节讲怎么用模式读别人的代码。

一、路标的作用

读陌生的类库,最怕的是【不知道从哪看起】。 一旦认出模式,结构就露出来了:看到 Iterable 你就知道该实现 __iter__。 不用读实现——这就是 6.9 说的【思想集】在起的作用。

二、实测标准库里的路标

collections.abc 里有 53 个抽象基类。 实测五个:Iterable(list 是)、Sized(dict 是)、Mapping(dict 是)、Sequence(tuple 是)、Callable(函数是)。 这五个名字就是五块路标——看到名字就知道该实现哪几个方法。

三、正确的阅读顺序

先认模式,再看实现。 反过来会被细节淹掉:一个模块三千行,你从第一行读起,读到一半就迷路了。 具体做法:先看它继承了什么、实现了哪些特殊方法——那几行就把结构说完了。

四、顺带的好处

写自己的类时,主动符合这些路标——用户就不用读你的实现。 实测:自己写的类实现 __iter__ 和 __len__ 之后,for、sum、list 全都能用(6.11 会看到)。 所以路标是双向的:读别人的时候用,写自己的时候立。

五、动手 Demo:设计模式是类库探险的路标

数一数 standard library 里有多少抽象基类。 再验证几个常见类型各符合哪块路标。

import collections.abc as abc
print(len([n for n in dir(abc) if not n.startswith("_")]))

print(isinstance([], abc.Iterable))
print(isinstance({}, abc.Mapping))
print(isinstance((1,), abc.Sequence))
print(isinstance(len, abc.Callable))

实跑输出:

--------------------------------------------------------------------
设计模式是类库探险的路标
--------------------------------------------------------------------

  读别人的类库时,**认出模式就等于认出了结构。**实测标准库里的对应:

      collections.abc 里的抽象基类      53 个
      前三个                            ABCMeta/AsyncGenerator/AsyncIterable

  路标(抽象基类)           实测     说明
  -------------------------------------------------
  Iterable(迭代器模式)     是       list 能 for
  Sized                      是       dict 有 len
  Mapping(映射)            是       dict 是映射
  Sequence                   是       tuple 是序列
  Callable                   是       函数能调用

  **这条路标的价值:看到 `Iterable` 你就知道该实现 `__iter__`,**
  **不用去读它的实现——这正是 6.9 说的【思想集】在起的作用。**
  **所以读类库的顺序是:先认模式,再看实现;反过来会被细节淹掉。**

实测:collections.abc 里 53 个抽象基类;list 是 Iterable、dict 是 Mapping、tuple 是 Sequence、函数是 Callable。 看到名字就知道该实现哪几个方法——所以读类库要先认模式再看实现。

30 秒实验

  1. 挑一个你不熟的库,先找它继承了哪些抽象基类。
  2. 用 isinstance 验证几个内置类型各符合哪些路标。

常见误区

  1. 以为模式要背完才能读代码。认出一块路标就够走一段。
  2. 以为路标只用来读。写自己的类时立路标,别人才好读你。
自测三问(点开对答案) 1. 路标的作用是什么? —— 认出一块抽象基类就知道该实现哪几个方法,不用读实现——先认模式再看实现。 2. 实测 `collections.abc` 里有多少个抽象基类? —— 53 个;实测 list 是 Iterable、dict 是 Mapping、tuple 是 Sequence、函数是 Callable。 3. 为什么说路标是双向的? —— 读别人的时候靠它认结构;写自己的类时主动实现这些协议,别人也就不用读你的实现。

相关笔记