鱼C论坛

 找回密码
 立即注册
楼主: 小甲鱼

[扩展阅读] super() 这么优秀,官方也极力推荐,但这里面有些坑你们可能把握不住…

  [复制链接]
发表于 2026-5-26 15:25:16 | 显示全部楼层
零基础入门学习Python封面
《零基础入门学习Python》
(最新版)
小甲鱼 著
立即购买
1
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2026-5-26 21:06:20 | 显示全部楼层
不知道
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2026-5-27 15:10:35 | 显示全部楼层
继承顺序为BDACE,C需要传参,但A没有
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2026-6-4 12:28:14 | 显示全部楼层
1
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2026-6-4 13:39:45 | 显示全部楼层
1
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2026-6-6 16:19:55 | 显示全部楼层
gfh
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2026-6-7 16:03:16 | 显示全部楼层
问题在于按照mro顺序,B后面没有任何类,所以报错了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2026-6-7 18:22:03 | 显示全部楼层
学习了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2026-6-12 15:57:34 | 显示全部楼层
D缺少输入参数arg
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2026-6-14 18:10:24 | 显示全部楼层
类c和类D没有定义self.arg = arg
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2026-6-15 15:55:19 | 显示全部楼层
学习
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2026-6-15 16:05:49 | 显示全部楼层
参数 520 没给到D
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2026-6-24 02:38:23 | 显示全部楼层
class E 中的super().__init__(arg) 应该去掉括号中的arg
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2026-6-26 16:17:50 | 显示全部楼层
参数多余
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2026-6-30 16:29:25 | 显示全部楼层
类B的super()?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2026-6-30 17:02:34 | 显示全部楼层
看完小甲鱼写的,对于钻石继承的第一个问题的打印顺序还是有懵,找Deepseek解析了一下。看完这段解析,如果看懂了,那后面的问题都能答出来了。

这个问题的核心在于:**MRO 决定的是 `super()` 调用“往里进”的顺序,而 `print` 写在 `super()` 后面,打印发生在“往外出”的时候。**

简单说:**调用链是“下潜”,打印链是“上浮”**。

---

## 一步步拆解执行过程(像 debugger 一样)

当你执行 `c = C()` 时,程序并不是按照“先 C 全部执行完,再 B1 全部执行完”的顺序,而是像钻套娃一样:

1. **进入 `C.__init__`**  
   执行到 `super().__init__()`,此时根据 MRO(C→B1→B2→A),`super()` 去找 **B1**。  
   **C 的 `print` 被暂停,还没执行。**

2. **进入 `B1.__init__`**  
   执行到 `super().__init__()`,根据 MRO,B1 的下一个是 **B2**。  
   **B1 的 `print` 被暂停,还没执行。**

3. **进入 `B2.__init__`**  
   执行到 `super().__init__()`,根据 MRO,B2 的下一个是 **A**。  
   **B2 的 `print` 被暂停,还没执行。**

4. **进入 `A.__init__`**  
   执行到 `super().__init__()`(调用 object,啥也不做),继续往下走,**执行 `print("哈喽,我是A~")`**。  
   **A 执行完毕,返回上一层(B2)。**

5. **回到 `B2` 的 `super()` 之后**  
   刚才卡在 `super()` 这里,现在继续往下走,**执行 `print("哈喽,我是B2~")`**。  
   **B2 执行完毕,返回上一层(B1)。**

6. **回到 `B1` 的 `super()` 之后**  
   继续往下走,**执行 `print("哈喽,我是B1~")`**。  
   **B1 执行完毕,返回上一层(C)。**

7. **回到 `C` 的 `super()` 之后**  
   继续往下走,**执行 `print("哈喽,我是C~")`**。

---

## 用一张图看懂

```
调用 super() 的顺序(下潜):  C  →  B1  →  B2  →  A
                               ↓     ↓     ↓     ↓
执行 print 的顺序(上浮):    C  ←  B1  ←  B2  ←  A
```

但 A 在最底层,所以先打印 A,然后逐层“浮”上来打印 B2、B1、C。

---

## 为什么是 B2 先于 B1,而不是 B1 先于 B2?

因为你的继承顺序是 `class C(B1, B2)`,MRO 算法保证 **B1 在 B2 前面**。

所以在“下潜”时:C 先找 B1,B1 找 B2,B2 找 A。  
在“上浮”时:A 回到 B2,B2 回到 B1,B1 回到 C。  
所以打印时 **B2 比 B1 先打印**(因为 B2 比 B1 更深一层)。

---

## 如果我把 `print` 放在 `super()` 前面,结果会怎样?

你可以试试把代码改成这样:

```python
class B1(A):
    def __init__(self):
        print("哈喽,我是B1~")   # 先打印
        super().__init__()       # 再调用
```

那么打印顺序就会变成 **C → B1 → B2 → A**,完美匹配 MRO。因为这时打印发生在“下潜”的路上。

---

## 一句话总结

> **MRO 决定的是 `super()` 找“下一个是谁”的顺序;而你看到的结果是 `print` 在递归返回时的顺序,所以恰好是 MRO 的倒序(除了最底层的 A)。**
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 前天 15:41 | 显示全部楼层
A到D之间缺少传递参数
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2026-7-10 17:27

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表