wbzxz 发表于 2023-6-10 18:16:23

请问能解释一下输出顺序吗?

>>> 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~

isdkz 发表于 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__()时会按照这个顺序打印出结果。

wbzxz 发表于 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~"没有打印出来呢?

isdkz 发表于 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__ 方法。
页: [1]
查看完整版本: 请问能解释一下输出顺序吗?