同样的mro顺序,不同的输出结果
没有用super()的代码
class A:
def __init__(self):
print("哈喽,我是A~")
class B1(A):
def __init__(self):
A.__init__(self)
print("哈喽,我是B1~")
class B2(A):
def __init__(self):
A.__init__(self)
print("哈喽,我是B2~")
class C(B1, B2):
def __init__(self):
B1.__init__(self)
B2.__init__(self)
print("哈喽,我是C~")
c = C()
print(C.__mro__)
哈喽,我是A~
哈喽,我是B1~
哈喽,我是A~
哈喽,我是B2~
哈喽,我是C~
(<class '__main__.C'>, <class '__main__.B1'>, <class '__main__.B2'>, <class '__main__.A'>, <class 'object'>)
用了super()的代码
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()
print(C.__mro__)
哈喽,我是A~
哈喽,我是B2~
哈喽,我是B1~
哈喽,我是C~
(<class '__main__.C'>, <class '__main__.B1'>, <class '__main__.B2'>, <class '__main__.A'>, <class 'object'>)
请问以上两段代码,mro的顺序是一样的,为什么用了super()的代码和未用的输入结果的顺序不同啊。一个是先输出“我是B2”,一个是先输出“我是B1”,谢谢指点。
这两段代码中的差异在于直接调用基类方法和使用 super() 的方式。当直接调用基类的 __init__ 方法时,会直接执行该方法,而不考虑方法解析顺序(MRO)中的其他类。然而, super() 的工作方式就有点不同。
Python的 super() 函数是用来调用父类(超类)的一个方法。它返回的是一个临时对象,这个对象就是父类或者是兄弟类。它并不是简单地找到其父类然后执行其父类的方法,而是按照MRO(Method Resolution Order,方法解析顺序)去查找下一个需要执行的类。
在使用了 super() 的代码中,Python的MRO遵循C3线性化或者叫做C3超类线性化。在类的继承关系中,先从自身开始查找,然后是父类,如果有多个父类,会先选择在类定义中排在前面的父类。
在你的例子中,MRO的顺序是C -> B1 -> B2 -> A。当在类C的 __init__ 方法中调用 super().__init__() 时,会根据MRO寻找到下一个类,也就是B1。然后在B1的 __init__ 中再次调用 super().__init__() ,继续按照MRO找到下一个类B2,同样地,在B2中再次调用 super().__init__() ,最后找到类A。
这就是为什么当使用 super() 时,输出的结果会按照MRO的顺序出现。相比之下,直接调用基类的 __init__ 方法不会考虑MRO,只会直接执行指定基类的方法,这就是为什么在未使用 super() 的代码中,类A的 __init__ 方法被调用了两次,因为它被B1和B2的 __init__ 方法分别调用了。 非常感谢您的指点,分析清晰,一语中的,向您学习!!!
页:
[1]