1、新式类和经典类
在python2.2之前, 基类如果不写(), 则表示为经典类;
在python2.2之后, 经典类不复存在, 只存在新式类. 如果基类谁都不继承的话, 则默认继承object.
2、MRO----()方法解释顺序
主要用于多继承时判断属性的路径(来自于哪个类).
经典类的MRO算法 ------树形结构的深度优先遍历
原则: 按继承顺序从左子树到右子树, 一条道走到黑.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class A: pass 2 class B(A): pass 3 class C(A): pass 4 class D(B, C): pass 5 class E: pass 6 class F(D, E): pass 7 class G(F, D): pass 8 class H: pass 9 class Foo(H, G): pass 10 # MRO 顺序: H G F D B A C E
3、新式类的MRO顺序 ----> 遵循C3算法
先由MRO确定一个线性序列, 然后查找路径由线性序列中类的顺序决定, C3算法就是生成这样的一个线性序列.
c3算法的核心是merge算法.
merge原则: 拿前一项的头和后面所有项的身体进行比较, 如果在后面没有出现, 则拿出这个头并划掉出现的所有该元素,前一项继续往后走;
如果在后面项中出现, 则前一项(a)剩余全部跳过, 比较第二项(b)(用第二项(b)的头和后面所有项的身体比较, 有的话继续跳过去, 比较第三项(c)), 啥时候没有出现, 拿出并划掉后继续返回前一项(a)剩下的元素继续比较.
注意: 可以这样查找: C3算法就是把每个环节多个类产生的共同继承留到最后去找.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class A: pass 2 class B(A): pass 3 class C(A): pass 4 class D(B, C): pass 5 class E(C, A): pass 6 class Y: pass 7 class F(D,Y, E): pass 8 class G(E): pass 9 class H(G, F): pass 10 11 # 先拆分 再从下往上合并, 把前一项的头和后面所有项的身体进行比较, 如果后面出现了则直接跳过, 没有的话前一项接着往后走 12 # S(H) = H + S(G) + S(F) + GF HGFD BYEC A 13 # S(G) = G + S(E) GECA 14 # S(F) = F + S(D) + S(Y) + S(E) + DYE FDBYECA 15 # S(E) = E + S(C) + S(A) + CA ECA 16 # S(D) = D + S(B) + S(C) + BC DBCA 17 # S(B) = B + S(A) BA 18 # S(C) = C + S(A) CA 19 print(H.mro()) # HGFD BYEC A
4、super() ----> 执行MRO中的下一个父类方法.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Foo: 2 def func1(self): 3 super().func1() # 找下一个父类 Bar 4 print("走你2") 5 6 class Bar: 7 def func1(self): 8 print("走你1") 9 10 class Ku(Foo,Bar): 11 def func1(self): 12 super().func1() # 找下一个父类 Foo 13 print("走你3") 14 15 k = Ku() 16 k.func1() 17 18 # MRO顺序: ku ----> Foo ----> Bar ----> object
5、已经有继承关系了还要用super()继承呢?
因为有时候普通的继承关系是满足不了需求的.
比如: 用父类的方法来完成自己的一部分代码, 这个时候就能用得到super()了.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Base: 2 def __init__(self,a,b,c): 3 self.a = a 4 self.b = b 5 self.c = c 6 7 class Foo(Base): 8 def __init__(self,a,b,c,d): 9 super(Foo, self).__init__(a,b,c) # 用父类方法来构造自己的a,b,c, 自己再添加self.d. 10 self.d = d # 如果用单纯的非super继承很难实现. 11 12 f = Foo(11,22,33,44) 13 print(f.a) 14 print(f.b) 15 print(f.c) 16 print(f.d)
再比如: 如果继承的多个类中都存在相同的方法, 使用super能很精准地定位到要执行方法的类.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Animal: 2 def act(self): 3 print("动物会动") 4 5 class Cat(Animal): 6 def act(self): 7 print("猫会动") 8 9 class BosiCat(Cat): 10 def act(self): 11 super(Cat, self).act() # 可以很精准地定位到执行cat()类的下一个类的act()方法, 不用super()很难定位精确. 12 print("波斯猫会动") 13 14 b = BosiCat().act()