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