Python多重继承

钻石继承(菱形继承)问题

钻石菱形

class A(object):
    def m(self):
        print("m of A called")

class B(A):
    def m(self):
        print("m of B called")
    
class C(A):
    def m(self):
        print("m of C called")

class D(B,C):
    pass

钻石问题主要关注如下两个问题(参考文章:python 多重继承的事):

  1. 父类方法的调用顺序上(下面一小节)
  2. 比如若B和C中的m方法也同时调用了A中的m方法时,重复执行的问题
class A:
    def m(self):
        print("m of A called")

class B(A):
    def m(self):
        print("m of B called")
        A.m(self)
    
class C(A):
    def m(self):
        print("m of C called")
        A.m(self)

class D(B,C):
    def m(self):
        print("m of D called")
        B.m(self)
        C.m(self)

输出结果:

m of D called
m of B called
m of A called
m of C called
m of A called

其实上面两个问题的根源都跟MRO有关,MRO(Method Resolution Order)也叫方法解析顺序,主要用于在多重继承时判断调的属性来自于哪个类,其使用了一种叫做C3的算法,其基本思想时在避免同一类被调用多次的前提下,使用广度优先和从左到右的原则去寻找需要的属性和方法。
问题二的解决方案如下:

class A(object):
    def m(self):
        print("m of A called")

class B(A):
    def m(self):
        print("m of B called")
        super().m()
    
class C(A):
    def m(self):
        print("m of C called")
        super().m()

class D(B,C):
    def m(self):
        print("m of D called")
        super().m()

输出如下:

m of D called
m of B called
m of C called
m of A called

多继承搜索__init__方法的两种策略

在当前类中没有init方法,木有覆盖的情况下,多重继承搜索策略(参考:python3 多继承搜索__init__方法的两种策略):

class A(object): 
    def __init__(self):
        print('A')
 
class B(object): 
    def __init__(self):
        print('B')

class C(A): 
    def __init__(self):
        print('C') 
 
class D(B): 
    def __init__(self):
        print('D') 
 
class E(C, D):
    pass

不同祖先

这种情形下,python3搜索__init__方法的顺序是 E->C->A->D->B

不同祖先

相同祖先

这种情况下python3搜索__init__方法的顺序是 E->C->D->A

相同祖先

在当前的类中,有init方法,在该init的方法中,有super().init()方法(只能调用第一个父类的方法),结论也是类似:

class A(object): 
    def __init__(self):
        print('A')
 
class B(object): 
    def __init__(self):
        print('B')

class C(A): 
    def __init__(self):
        print('C') 
 
class D(B): 
    def __init__(self):
        print('D') 
 
class E(C, D):
    def __init__(self):
        print('E')
        super().init()    

python 多重继承属性初始化

键值对初始化

知识摘抄过来,没有实战经验

# base classes

class A:
    def __init__(self, a1, a2, **kwargs):
        super().__init__(**kwargs)
        self.a1 = a1
        self.a2 = a2

    def funa(self):
        print("I'm funa")

class B:
    def __init__(self, b1, **kwargs):
        super().__init__(**kwargs)
        self.b1 = b1

    def funb(self):
        print("I'm funb")
        
class C:
    def __init__(self, c1, c2, c3, **kwargs):
        super().__init__(**kwargs)
        self.c1 = c1
        self.c2 = c2
        self.c3 = c3

    def func(self):
        print("I'm func")
# derived classes

class X(B, A, C):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        
class Y(A, B):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

调用类名+ init 方法

class A(object):
    def __init__(self, a1,a2):
        # super(ClassName, self).__init__()
        self.a1 = a1
        self.a2 = a2

    def funa(self):
        print("I'm funa")

class B(object):
    def __init__(self, b1):
        # super(ClassName, self).__init__()
        self.b1 = b1

    def funb(self):
        print("I'm funb")
        
class C(A, B):
    def __init__(self, a1, a2, b1):
        A.__init__(self, a1, a2)
        B.__init__(self, b1)

c = C(1, 2, 3)
dir(c)

参考文章

原文地址:https://www.cnblogs.com/meiguhuaxian/p/13063659.html