鱼C论坛

 找回密码
 立即注册
查看: 2372|回复: 3

[已解决]请问能解释一下输出顺序吗?

[复制链接]
发表于 2023-6-10 18:16:23 | 显示全部楼层 |阅读模式

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

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

x
>>> class A:
...     def __init__(self):
...         print("哈喽,我是A~")
...
>>> class B1(A):
...     def __init__(self):
...        super().__init__()
...        print("哈喽,我是B1~")
...                
>>> class B2(A):
...     def __init__(self):
...         super().__init__()
...         print("哈喽,我是B2~")
...
>>> class C(B1, B2):
...     def __init__(self):
...         super().__init__()
...         print("哈喽,我是C~")
...
>>> c = C()
哈喽,我是A~
哈喽,我是B2~
哈喽,我是B1~
哈喽,我是C~

代码与输出结果如上。对上面的输出结果不理解,请教各位。

我个人理解,输出结果顺序应该是


哈喽,我是A~
哈喽,我是B1~
哈喽,我是B2~
哈喽,我是C~
最佳答案
2023-6-10 18:27:38
这个例子演示的是 Python 中的多重继承和方法解析顺序(Method Resolution Order, MRO)。多重继承是一种让一个类可以从多个父类继承属性和方法的能力。Python中的MRO则确定了子类继承父类时的调用顺序。

在Python中,MRO由一个特定的算法决定,叫做C3线性化或者也叫做查尔斯顺序(Charles's order)。这个算法确保了每个类都会先于其所有子类被访问,而且每个父类也会按照它们在列表中的顺序被访问。

在你给出的例子中,我们有四个类A,B1,B2和C。C是B1和B2的子类,B1和B2都是A的子类。根据C3线性化,其方法解析顺序为C -> B1 -> B2 -> A。

因此,在实例化C类时,会首先调用A的初始化方法,然后是B2的初始化方法,接着是B1的初始化方法,最后是C的初始化方法。所以输出的结果是:
哈喽,我是A~
哈喽,我是B2~
哈喽,我是B1~
哈喽,我是C~

这就是为什么在调用  super().__init__()  时会按照这个顺序打印出结果。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-6-10 18:27:38 | 显示全部楼层    本楼为最佳答案   
这个例子演示的是 Python 中的多重继承和方法解析顺序(Method Resolution Order, MRO)。多重继承是一种让一个类可以从多个父类继承属性和方法的能力。Python中的MRO则确定了子类继承父类时的调用顺序。

在Python中,MRO由一个特定的算法决定,叫做C3线性化或者也叫做查尔斯顺序(Charles's order)。这个算法确保了每个类都会先于其所有子类被访问,而且每个父类也会按照它们在列表中的顺序被访问。

在你给出的例子中,我们有四个类A,B1,B2和C。C是B1和B2的子类,B1和B2都是A的子类。根据C3线性化,其方法解析顺序为C -> B1 -> B2 -> A。

因此,在实例化C类时,会首先调用A的初始化方法,然后是B2的初始化方法,接着是B1的初始化方法,最后是C的初始化方法。所以输出的结果是:
哈喽,我是A~
哈喽,我是B2~
哈喽,我是B1~
哈喽,我是C~

这就是为什么在调用  super().__init__()  时会按照这个顺序打印出结果。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-10 21:45:42 | 显示全部楼层
isdkz 发表于 2023-6-10 18:27
这个例子演示的是 Python 中的多重继承和方法解析顺序(Method Resolution Order, MRO)。多重继承是一种让一 ...

class A:
    def __init__(self):
        print("哈喽,我是A~")

class B1(A):
    def __init__(self):
       super().__init__()
       print("哈喽,我是B1~")

class B2:
    def __init__(self):
        super().__init__()
        print("哈喽,我是B2~")

class C(B1, B2):
    def __init__(self):
        super().__init__()
        print("哈喽,我是C~")

c = C()
哈喽,我是A~
哈喽,我是B1~
哈喽,我是C~

非常感谢您的指点,我向多问一句,上面这个代码解析方法是什么啊?(按照您的分析思路,是不是应该是C -> B1 -> A ->B2)
为什么“哈喽,我是B2~"没有打印出来呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-6-10 21:51:07 | 显示全部楼层
wbzxz 发表于 2023-6-10 21:45
非常感谢您的指点,我向多问一句,上面这个代码解析方法是什么啊?(按照您的分析思路,是不是应该 ...

你的观察很好!在你的第二个代码片段中,注意到B2类的 __init__ 方法调用了 super().__init__() ,但是B2类并没有明确指定父类。在Python中,如果类定义时没有指定父类,则默认的父类是object类,object是所有Python类的最基本的类。

在这个情况下,当B2的 __init__ 方法执行 super().__init__() 时,它实际上是调用了object类的 __init__ 方法,而不是A类的 __init__ 方法。因此,A类的 __init__ 方法在B1中被调用,然后直接跳过了B2,所以并没有打印“哈喽,我是B2~”。

所以,初始化C类的解析顺序为C -> B1 -> A。这就解释了为什么“哈喽,我是B2~"没有被打印出来。

如果你希望在初始化C类时同时调用B2的初始化方法,那么你需要让B2类也继承自A类或者其它具有 __init__ 方法的类。这样在执行 super().__init__() 时就会调用那个类的 __init__ 方法。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-12-26 21:45

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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