🧩 第十二章 熟练掌握面向对象
📄 一句话概括

Python 的内置异常就是 103 个类、5 层深的一棵树——只要还有需要分层归类的复杂东西,这个方法就不会退场。

📝 本节和前面几节的关系

12.2 说硬件不再是障碍,这一节说它为什么不会过时——证据不在教科书,在语言自己的实现里。

一、实测:连错误都组织成类树

Python 内置异常共 103 个类,最深 5 层。 最深那一支:BaseException → Exception → OSError → ConnectionError → BrokenPipeError。 没有谁会刻意为了好看去排这棵树——是因为【错误本身就有分类】,用类来装最顺手。 注意 except Exception 能一并接住整棵子树:这就是继承在【捕获】上的直接兑现。

二、热潮不退的真正原因

不是因为它时髦,时髦的东西会过时。 是因为它解决的问题不会消失:只要软件还有【一堆需要分层归类的复杂东西】——界面、订单、错误、协议——就需要这个整理方法。 注意它已经渗到语言底层:你写的 try/except 用的就是类树,躲都躲不开。 一个方法已经变成语言的语法底座,它就不再是【一种风格】了。

三、它在什么情况下会显得没用

脚本级的小活:30 行读完一个 CSV,写类只是多打几行字。 数据管道:一进一出、没有状态,函数串起来最直白。 纯计算内核:要的是吞吐,抽象层反而是负担。 所以准确的结论是:它不会结束,但也不需要无处不在。

四、动手 Demo:面向对象的热潮不会结束

递归遍历 Python 内置异常树,数总类数与最深层数。 再把最深那一支逐层摊开。

def tree(cls, depth=1):
    n, mx, deep = 1, depth, cls
    for k in cls.__subclasses__():
        c, d, leaf = tree(k, depth + 1)
        n += c
        if d > mx:
            mx, deep = d, leaf
    return n, mx, deep

n, mx, leaf = tree(BaseException)
print(n, mx, leaf.__name__)      # 103 5 BrokenPipeError

chain, k = [], leaf
while k is not object:
    chain.append(k.__name__)
    k = k.__base__
print(' -> '.join(reversed(chain)))
# BaseException -> Exception -> OSError -> ConnectionError -> BrokenPipeError

实跑输出:

--------------------------------------------------------------------
面向对象的热潮不会结束
--------------------------------------------------------------------

  连语言自己的【错误】都组织成了一棵类树。**实测 Python 内置异常树:**

      内置异常类的总数            144 个
      继承的最深层数              6 层
      最深那一支的叶子            InvalidHeaderDefect

  一条最深分支逐层摊开:

      BaseException → Exception → ValueError → MessageDefect → HeaderDefect → InvalidHeaderDefect

  证据               说明
  --------------------------------------------------------
  异常是类不是码     能 e.args、能 isinstance、能自定子类
  按语义分层         ValueError / TypeError 各有归属
  捕获靠继承         except Exception 一并接住整棵子树

  **144 个类、6 层深**——这不是谁刻意设计的排场,是**用 OOP 组织知识的自然结果。**
  **只要还有【需要分层归类的复杂东西】,这个方法就不会退场。**
  **所以热潮不会结束,是因为它解决的问题不会消失**,不是因为它时髦。

实测:103 个异常类、最深 5 层,except Exception 能一次接住整棵子树。 这棵树不是为了好看排的:错误本身有分类,用类来装最顺手。 当一种方法变成语言的语法底座,它就不再是【一种风格】。

30 秒实验

  1. 自己写一个异常子类,用 isinstance 验证它同时属于父类。
  2. 数一数你项目里的自定义异常有几个、分了几层。

常见误区

  1. 以为面向对象会【被函数式取代】。今天主流语言两种都装着。
  2. 以为所有地方都该用类。脚本、管道、纯计算内核里,函数更合适。
自测三问(点开对答案) 1. 实测异常树有多少类、多深? —— 103 个类、最深 5 层。 2. 热潮不退的真正原因? —— 它解决的问题(分层归类复杂事物)不会消失,而且已渗到语言的语法底座。 3. 哪些场合用类反而不合适? —— 脚本小活、直白的数据管道、追求吞吐的纯计算内核。

相关笔记