鱼C论坛

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

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

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

使用道具 举报

发表于 2025-11-21 19:04:14 | 显示全部楼层
arg未绑定对象
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-11-26 15:16:47 | 显示全部楼层
父类的构造方法没有入参
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-11-26 16:31:52 | 显示全部楼层
A,B无arg参数
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-12-5 08:39:12 | 显示全部楼层
1
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2025-12-11 06:27:29 | 显示全部楼层
要理解 “D.__init__需要 arg 参数但未传递”,关键在于多继承的方法解析顺序(MRO) 和super () 的参数传递逻辑,结合你的代码结构一步步拆解就很清晰了:
先明确类的继承关系和每个类的__init__参数
假设已修正构造方法名为__init__(原代码是_init_,这是基础错误),各阶级的__init__定义如下:
python
运行
class A:
    def __init__(self):  # 无参数
        super().__init__()

class B:
    def __init__(self):  # 无参数
        super().__init__()

class C(A):
    def __init__(self, arg):  # 需要1个参数arg
        super().__init__()  # 调用时没传参数

class D(B):
    def __init__(self, arg):  # 需要1个参数arg
        super().__init__()  # 调用时没传参数

class E(C, D):
    def __init__(self, arg):  # 需要1个参数arg
        super().__init__(arg)  # 调用时传了arg
核心:MRO(方法解析顺序)决定调用链
当实例化E时(e = E(520)),Python 会按MRO 顺序调用所有相关类的__init__。对于E(C, D),MRO 顺序是:E → C → A → D → B → object
(可以通过E.__mro__查看这个顺序,这是 Python 多继承中 “先左后右、深度优先” 的解析规则)
一步步看参数传递过程
调用 E 的__init__:E.__init__(self, 520) 执行,内部调用 super().__init__(520)。根据 MRO,super()此时指向C,所以实际调用 C.__init__(self, 520)(参数520被传递给 C,符合 C 需要arg的要求)。
调用 C 的__init__:C.__init__(self, 520) 执行,内部调用 super().__init__()(注意:这里没传任何参数)。根据 MRO,super()此时指向A,所以实际调用 A.__init__(self)(A 不需要参数,没问题)。
调用 A 的__init__:A.__init__(self) 执行,内部调用 super().__init__()(依然没传参数)。根据 MRO,super()此时指向D(因为 A 的下一个是 D),所以实际调用 D.__init__(self)。
问题出在这里:调用 D 的__init__D.__init__ 的定义是 def __init__(self, arg):,它必须接收 1 个参数 arg,但此时从 A 的super()过来的调用是 D.__init__(self)(没有传arg)。因此,Python 会报错:TypeError: D.__init__() missing 1 required positional argument: 'arg'。
一句话总结
因为 MRO 顺序要求在调用完 A 的__init__后必须调用 D 的__init__,但 D 的__init__需要arg参数,而整个调用链中(从 C 到 A 的super())没有传递这个参数,导致 D 的__init__参数缺失。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-12-11 11:15:44 | 显示全部楼层
偏离
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2025-12-14 10:59:25 | 显示全部楼层
应该是A的super没有放置参数
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-12-18 15:09:03 | 显示全部楼层
好难啊
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-12-24 17:35:28 | 显示全部楼层
学习学习
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 7 天前 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 7 天前 | 显示全部楼层
>>> class A:
...     def say(self):
...         print("FishA")
...        
>>> class B:
...     def say(self):
...         print("FishB")
...
>>> class C(A, B):
...     def say(self):
...         super().say()
...
>>> c = C()
>>> c.say()
FishA

很好!你这个例子其实正好展示了 **多继承 + super() + MRO 方法解析顺序** 的效果。我们一步一步来看为什么最后打印的是 **FishA**。

---

## 🔍 代码回顾

```python
class A:
    def say(self):
        print("FishA")

class B:
    def say(self):
        print("FishB")

class C(A, B):
    def say(self):
        super().say()

c = C()
c.say()
```

输出:

```
FishA
```

---

## ✅ 关键点:`super()` + MRO

当你执行:

```python
c.say()
```

时发生了:

1️⃣ 进入 `C.say()`
2️⃣ `super().say()` 被调用
3️⃣ super 并不是“只找父类 A”
它是按 **MRO(方法解析顺序)** 找方法的。

---

## 📌 C 的 MRO 顺序是:

你可以打印看看:

```python
print(C.mro())
```

结果:

```
[<class '__main__.C'>,
<class '__main__.A'>,
<class '__main__.B'>,
<class 'object'>]
```

顺序是:

```
C → A → B → object
```

---

## &#10024; super() 的工作方式

在 `C.say()` 里:

```python
super().say()
```

并不是“找父类 A”这么简单,而是:
&#128073; 按 MRO 顺序
&#128073; 从 **C 的下一个类(A)开始找 say()**

A 里刚好有:

```python
def say(self):
    print("FishA")
```

所以就打印:

```
FishA
```

B 根本没机会执行。

---

## &#10067;如果我们改继承顺序呢?

把 C 改成:

```python
class C(B, A):
```

再执行:

```python
c.say()
```

输出将变成:

```
FishB
```

因为 MRO 变为:

```
C → B → A → object
```

---

## &#127919; 总结一句话

`super()` 在多继承中不是“找父类”,
而是“**按 MRO 顺序继续往后找**”。

所以:

* C(A, B) → 找到 A.say → 打印 FishA
* C(B, A) → 找到 B.say → 打印 FishB

---

如果你还想继续深入,比如:

* super() 到底是怎么跳转的?
* 多层继承链如何工作?
* 和 Java/C++ 的 super 有啥不同?

我可以继续帮你拆得更细 &#128522;

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 7 天前 | 显示全部楼层
又深刻的学习一遍
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-1-2 07:21

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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