Python类多重继承只能从一个父类继承变量?

um6iljoc  于 2023-08-08  发布在  Python
关注(0)|答案(2)|浏览(152)

我对Python类从多个父类继承的方式感到困惑。
如果父类都继承自同一个祖类,一切都很棒。

# grand-parent class
class Z():
    def __init__(self):
        pass

# parent class A
class A(Z):
    def __init__(self):
        super().__init__()
        self.x = 1

# parent class B
class B(Z):
    def __init__(self):
        super().__init__()
        self.y = 2

# parent class C
class C(Z):
    def __init__(self):
        super().__init__()
        self.z = 3

# target class D
class D(A, B, C):
    def __init__(self):
        super().__init__()

d = D()
print(vars(d))
#{'x': 1, 'y': 2, 'z': 3}

字符串
如果没有相同的祖父类,则只继承第一个父类的变量。

# parent class A
class A():
    def __init__(self):
        self.x = 1

# parent class B
class B():
    def __init__(self):
        self.y = 2

# parent class C
class C():
    def __init__(self):
        self.z = 3

# target class D
class D(A, B, C):
    def __init__(self):
        super().__init__()

d = D()
print(vars(d))
#{'x': 1}

wf82jlnq

wf82jlnq1#

Python的方法解析顺序是从左到右。它只会调用第一个类的init方法(本例中为A)。这会给予你想要的结果-

class A():
def __init__(self):
    super().__init__()
    self.x = 1

# parent class B
class B():
    def __init__(self):
        super().__init__()
        self.y = 2

# parent class C
class C():
    def __init__(self):
        self.z = 3

# target class D
class D(A, B, C):
    def __init__(self):
        super().__init__()

d = D()
print(vars(d))

字符串

ljo96ir5

ljo96ir52#

在Python中,当一个类从多个父类继承时,称为多重继承。在给定的代码中,类A、B和C是没有任何直接父类的独立类,但它们用作目标类D的基类。即使这些类没有显式的父类,它们仍然需要在它们的init方法中调用super().init(),因为它们参与Python使用的方法解析顺序(MRO),以确定父类的init方法的调用顺序。
方法解析顺序(MRO)是Python在类层次结构中搜索方法和属性的特定顺序。它是使用C3线性化算法确定的,这有助于解决在多继承场景中可能出现的潜在模糊性和冲突。
在您的示例中,当创建类D的示例时,它继承自类A、B和C。MRO是以从左到右、深度优先的方式确定的,因此它遵循基类的顺序:
MRO(D)= [D,A,B,C]
让我们来分析一下为什么super().init()调用在每个类中都是必要的:

A类:它没有父类,但它仍然包含在MRO中,因为它是类D的继承链的一部分。类A中的super().init()调用将调用类B(MRO中的下一个类)的init方法,后者又将调用类C的init方法。虽然类A没有自己的初始化逻辑,但调用super().init()来维护正确的MRO并确保执行其他类的初始化逻辑是必要的。
B类:与类A类似,类B没有任何直接的父类,但作为类D的继承链的一部分参与MRO。类B中的super().init()调用将调用类C的init方法,这是MRO中的下一个类。
C类:类C是类D的MRO中的最后一个类,并且它用值3初始化属性z。
D类:最后,当您创建类D的示例时,它的init方法将被调用,并且它将调用super().init()以根据MRO按正确的顺序触发类A、B和C的初始化过程。

因此,当您创建类D的示例时,类A、B和C的所有init方法都以正确的顺序执行,并且您最终得到一个具有属性x、y和z的对象,每个属性都使用各自的值进行了初始化。
总而言之,即使类A和B没有直接的父类,它们也是类D的多重继承链的一部分,需要super().init()调用来确保遵循正确的MRO,并且正确执行所有基类的初始化逻辑。

相关问题