鱼C论坛

 找回密码
 立即注册
查看: 883|回复: 11

[已解决]关于python38讲 第六题的疑惑

[复制链接]
发表于 2020-3-24 18:58:48 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
这是我做出来的答案:
class A():
    def __init__(self):
        print("进入A…")
        print("离开A…")

class B(A):
    def __init__(self):
        print("进入B…")
        A.__init__(self)
        print("离开B…")
        
class C(A):
    def __init__(self):
        print("进入C…")
        A.__init__(self)
        print("离开C…")

class D(B, C):
    def __init__(self):
        print("进入D…")
        super().__init__()
        print("离开D…")
调用:
d = D()
结果:
进入D…
进入B…
进入A…
离开A…
离开B…
离开D…

#标准答案
class A():
    def __init__(self):
        print("进入A…")
        print("离开A…")

class B(A):
    def __init__(self):
        print("进入B…")
        super().__init__()#和调用未绑定的父类方法有什么不同,为什么产生了不同的结果
        print("离开B…")
        
class C(A):
    def __init__(self):
        print("进入C…")
        super().__init__()
        print("离开C…")

class D(B, C):
    def __init__(self):
        print("进入D…")
        super().__init__()
        print("离开D…")

d = D()
结果:
进入D…
进入B…
进入C…
进入A…
离开A…
离开C…
离开B…
离开D…


我的答案和标准答案,不同在类B和类C中未使用super()函数,而是调用了未绑定的父类方法,按道理来说结果应该是一样的,只有类D里调用了super()方法,它应该就会自动讲类A找出来。但是为什么我的结果与标准答案结果,少了一个类C的__init__方法的调用呢
最佳答案
2020-3-24 19:41:02
这是多重继承时初始化函数__init__()的内容,这个涉及到super()和__mro__的用法。
在继承的时候,子类中若需要调用父类的__init__()函数,则需要用super().__init__()。但若是多重继承,什么时候调用哪一个父类的__init__()函数,是由__mro__列表顺序给出的。

在你的这个程序中,D类的__mro__表如下:
<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>
当创建D类的实例化时,会先调用D类的__init__()函数。之后每遇到一次super().__init__()函数就会从上表 中向后找一个父类去执行它的__init__()函数,一直到列表为空或者最后一个执行的__init__()函数中没有super()__init__()函数为止。
我们现在看一下你的程序执行过程:先执行D的__init__()函数,遇到super;然后去执行B的__init__()函数,再次遇到super;接着去执行C的__init__()函数,C中没有遇到super函数,执行完毕之后返回B的__init__()函数;然后返回D的__init__()函数,结束。

假如,C中有super,而B中没有super。那么结果会更短,从D的__init__()函数进入B的__init__()函数,然后返回D的__init__()函数,结束。
看看之前回复的一个帖子,我当时写的很详细。 一一复制过来太麻烦了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-3-24 19:41:02 | 显示全部楼层    本楼为最佳答案   
这是多重继承时初始化函数__init__()的内容,这个涉及到super()和__mro__的用法。
在继承的时候,子类中若需要调用父类的__init__()函数,则需要用super().__init__()。但若是多重继承,什么时候调用哪一个父类的__init__()函数,是由__mro__列表顺序给出的。

在你的这个程序中,D类的__mro__表如下:
<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>
当创建D类的实例化时,会先调用D类的__init__()函数。之后每遇到一次super().__init__()函数就会从上表 中向后找一个父类去执行它的__init__()函数,一直到列表为空或者最后一个执行的__init__()函数中没有super()__init__()函数为止。
我们现在看一下你的程序执行过程:先执行D的__init__()函数,遇到super;然后去执行B的__init__()函数,再次遇到super;接着去执行C的__init__()函数,C中没有遇到super函数,执行完毕之后返回B的__init__()函数;然后返回D的__init__()函数,结束。

假如,C中有super,而B中没有super。那么结果会更短,从D的__init__()函数进入B的__init__()函数,然后返回D的__init__()函数,结束。
看看之前回复的一个帖子,我当时写的很详细。 一一复制过来太麻烦了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-24 21:52:33 | 显示全部楼层
sunrise085 发表于 2020-3-24 19:41
这是多重继承时初始化函数__init__()的内容,这个涉及到super()和__mro__的用法。
在继承的时候,子类中若 ...

意思就是super()函数的默认执行顺序是按__mor__表来的?我的代码的执行顺序实际上是D-B,B中没有super()函数,就没有继续向C执行,而是将B的__init__函数执行完之后,返回D的__init__函数了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-24 21:54:55 | 显示全部楼层
sunrise085 发表于 2020-3-24 19:41
这是多重继承时初始化函数__init__()的内容,这个涉及到super()和__mro__的用法。
在继承的时候,子类中若 ...

就是super()函数会按__mor__表顺序,来执行。直到列表为空或者没有super()函数为止。然后依次逐层返回
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-24 21:56:20 | 显示全部楼层
两仪shiki 发表于 2020-3-24 21:52
意思就是super()函数的默认执行顺序是按__mor__表来的?我的代码的执行顺序实际上是D-B,B中没有super()函 ...

是的。你的程序中 B的__init__中没有super,所以不会按照__mro__去执行C的__init__,但是有个确切的A.__init__(self),则会去执行A的__init__
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-24 21:59:55 | 显示全部楼层
sunrise085 发表于 2020-3-24 21:56
是的。你的程序中 B的__init__中没有super,所以不会按照__mro__去执行C的__init__,但是有个确切的A.__i ...

谢谢,那个帖子的回答写的很好,很受启发
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-24 22:00:03 | 显示全部楼层
两仪shiki 发表于 2020-3-24 21:54
就是super()函数会按__mor__表顺序,来执行。直到列表为空或者没有super()函数为止。然后依次逐层返回

是的。你可以看看给你的链接,那个帖子中回答的很详细。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-24 22:22:00 | 显示全部楼层
本帖最后由 两仪shiki 于 2020-3-24 22:24 编辑
sunrise085 发表于 2020-3-24 21:56
是的。你的程序中 B的__init__中没有super,所以不会按照__mro__去执行C的__init__,但是有个确切的A.__i ...


super(类名,self).__init__()函数会按顺序将当前层到目标层之间的类对象全部跳过?然后再向后继续执行?这个有点强大啊,但是对于我这种菜鸡,感觉好容易弄错啊。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-24 22:34:36 | 显示全部楼层
两仪shiki 发表于 2020-3-24 22:22
super(类名,self).__init__()函数会按顺序将当前层到目标层之间的类对象全部跳过?然后再向后继续执行 ...

你可以试一下嘛
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-24 22:43:16 | 显示全部楼层

我已经试过你的代码了,感觉就是这样的,D-E-列表末尾,中间的类对象全部被跳过了,所以结果是:进入F…
进入E…
离开E…
离开F…

我尝试将E中的super(A,self)改成了super(C,self),那样顺序就变成了D-E-A,然后结果就是:
进入F…
进入E…
进入A…
离开A…
离开E…
离开F…

我尝试将E中的super(A,self)改成了super(B,self),那样顺序就变成了D-E-C(C里面没有super()函数,所以不会向下继续执行),然后结果就是:
进入F…
进入E…
进入C…
离开C…
离开E…
离开F…
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-24 22:44:51 | 显示全部楼层

我现在有了个新问题,__mro__的顺序是怎么决定的,我现在有点疑惑,我感觉不是按顺序决定的。因为F的__mro__顺序和我想的有点出入
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-24 23:00:39 | 显示全部楼层

__mro__的命名规律,我也找出来了,是按顺序来的,不够它会按继承关系将一个类的顺序深挖到底,然后才会转向另一个与之平行的类,进行排序,谢谢大佬
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-25 09:29

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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