钻石继承(菱形继承)问题
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 多重继承的事):
- 父类方法的调用顺序上(下面一小节)
- 比如若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)