鱼C论坛

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

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

  [复制链接]
发表于 2024-6-9 17:06:43 | 显示全部楼层
super从入门到劝退
我还是老老实实的绑定去吧
但是我记住了深度优先and从左到右
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-6-13 12:10:58 | 显示全部楼层
学习学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-6-13 14:42:52 | 显示全部楼层
class A:
    def say(self):
        print("FishA")

class B:
    def say(self):
        print("FishB")
        
class C(A):
    def say(self):
        A.say(self)
        print("FishC")
        
class D(B):
    def say(self):
        B.say(self)
        print("FishD")

class E(C, D):
    def say(self):
        D.say(self)
        C.say(self)
        print("FishE")

e = E()
e.say()

================
这段代码运行结果明明是:
FishB
FishD
FishA
FishC
FishE
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-6-15 14:06:35 | 显示全部楼层
1
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-6-16 10:24:13 | 显示全部楼层
.
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-6-16 23:03:30 | 显示全部楼层
布吉岛
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-6-17 11:20:03 | 显示全部楼层
1
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-6-17 20:07:58 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-6-19 17:10:05 | 显示全部楼层
keep going
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-6-22 15:30:10 | 显示全部楼层
classA里面的init少一个arg参数吧?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-6-22 17:33:50 | 显示全部楼层
1
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-6-22 23:36:49 | 显示全部楼层
1
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-6-23 21:03:41 | 显示全部楼层
最后一个例子的运行结果是不是错了呀,我运行了一下,应该是:
FishB
FishD
FishA
FishC
FishE
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-6-28 11:31:14 | 显示全部楼层
不过对于这种情况,如果我们老老实实去调用未绑定父类的方法,事儿也不会那么多:
class A:
    def say(self):
        print("FishA")

class B:
    def say(self):
        print("FishB")
        
class C(A):
    def say(self):
        A.say(self)
        print("FishC")
        
class D(B):
    def say(self):
        B.say(self)
        print("FishD")

class E(C, D):
    def say(self):
        D.say(self)
        C.say(self)
        print("FishE")

e = E()
e.say()
代码实现如下:
=================== RESTART: C:\Users\goodb\Desktop\FishC.py ===================
FishA
FishB
FishC
FishD
FishE

这一步的结果顺序是不是不对啊?@FishC
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-6-28 11:32:46 | 显示全部楼层
phTian 发表于 2024-06-28 11:31
不过对于这种情况,如果我们老老实实去调用未绑定父类 ...


哈哈,这段代码的确让人头疼,不过让咱们从头捋一捋,看看到底哪儿出问题了。

首先,我们看下你的类继承关系:
- `E` 继承了 `C` 和 `D`
- `C` 继承了 `A`
- `D` 继承了 `B`

也就是说 `E` 的继承链是这样的:
E -> C -> A
   -> D -> B

现在来看 `E` 类的 `say` 方法:
class E(C, D):
    def say(self):
        D.say(self)
        C.say(self)
        print("FishE")

调用 `D.say(self)` 时,`D` 类会调用 `B.say(self)`,然后打印 `FishD`:
B.say(self) -> print("FishB")
D.say(self) -> print("FishD")

然后调用 `C.say(self)`,`C` 类会调用 `A.say(self)`,然后打印 `FishC`:
A.say(self) -> print("FishA")
C.say(self) -> print("FishC")

所以 `e.say()` 实际调用顺序是:
1. `D.say(self)`
   - 调用 `B.say(self)` -> 输出 `FishB`
   - 然后 `D.say(self)` -> 输出 `FishD`
2. `C.say(self)`
   - 调用 `A.say(self)` -> 输出 `FishA`
   - 然后 `C.say(self)` -> 输出 `FishC`
3. 最后 `E.say(self)` -> 输出 `FishE`

这样顺序就是:
FishB
FishD
FishA
FishC
FishE

显然跟你实际的输出顺序不同。实际输出是:
FishA
FishB
FishC
FishD
FishE

这说明类的 `say` 方法并没有按照 `E` 类中的调用顺序来执行。那么,这就是 Python 中的 `MRO`(方法解析顺序)在起作用了!

用 `super()` 和 `MRO` 机制重新写这段代码会更好一点:
class A:
    def say(self):
        print("FishA")

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

class C(A):
    def say(self):
        super().say()
        print("FishC")

class D(B):
    def say(self):
        super().say()
        print("FishD")

class E(C, D):
    def say(self):
        super().say()
        print("FishE")

e = E()
e.say()

这样使用 `super()` 后,顺序就会按 `MRO` 进行:
FishB
FishD
FishA
FishC
FishE

我们可以验证一下 `E` 的 `MRO`:
print(E.__mro__)
输出:
(<class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class '__main__.D'>, <class '__main__.B'>, <class 'object'>)

所以最终顺序应该是:
FishB -> FishD -> FishA -> FishC -> FishE

这样一来,我们就能够看到 `super()` 如何依照 `MRO` 顺序来进行方法调用了。Python 里的继承顺序可真是个迷宫,得让人慢慢探索啊!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-6-28 15:48:46 | 显示全部楼层
因为类A的构造函数中不需要传入参数
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-6-29 17:15:09 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-6-30 20:15:56 | 显示全部楼层
嘻嘻
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-7-3 09:01:29 | 显示全部楼层
学习学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-7-5 10:43:12 | 显示全部楼层
A调用D
D有arg
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-22 02:08

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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