一、判断继承
1. issubclass
- class Base:
- pass
-
- class Foo(Base):
- pass
-
- class Bar(Foo):
- pass
-
- print(issubclass(Bar, Foo)) # True
- print(issubclass(Foo, Bar)) # False
- print(issubclass(Bar, Base)) # True
二、多继承
- python支持多继承,一个类可以拥有多个父类
- 经典类:在python2.2之前版本使用的是经典类,经典类在基类的根如果什么都不写,不示继承xxx
- 新式类:在python2.2之后版本使用的是新式类,新式类的特点是基类的根是object
- python3使用的都是新式类,如果基类谁都不继承。那这个类会默认继承object
三、MRO
在多继承中,当多个父类出现了重名方法时,此时就涉及到如何查找父类方法的问题,即MRO(method resolution order)问题。
在python中,不同的版本中使用的是不同的算法来完成MRO的
1. 经典类的MRO
- 采用的是树型结构的深度优先遍历
- 深度优先遍历:从左往右,一条道走到黑
- class A:
- pass
-
- class B(A):
- pass
-
- class C(A):
- pass
-
- class D(B, C):
- pass
-
- class E:
- pass
-
- class F(E, B):
- pass
-
- class G(F, D):
- pass
-
- class H:
- pass
-
- class Foo(H, G):
- pass
继承关系图如下:
图1 继承关系图
类的MRO:Foo ---> H ---> G ---> F ---> E ---> B ---> A --->D ---> C
2. 新式类的MRO—C3算法
步骤:
- 先拆分
- 再合并:从下向上合并,拿出每一项的头和后一项的身体进行比较,如果出现了,就过,从后一项的头继续去比较,如果不出现就拿出来
- class A:
- pass
- class B(A):
- pass
- class C(A):
- pass
- class D(B, C):
- pass
- class E(C, A):
- pass
- class F(D, E):
- pass
- class M(F, E):
- pass
- class N:
- pass
- class P(M,N):
- pass
- class G(P):
- pass
- class O:
- pass
- class X(O):
- pass
- class H(G, X, F):
- pass
- print(H.__mro__)
结果:
(<class '__main__.H'>, <class '__main__.G'>, <class '__main__.P'>, <class '__main__.M'>, <class '__main__.X'>, <class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class '__main__.N'>, <class '__main__.O'>, <class 'object'>)
1) 先拆分:设L为查找方法的MRO顺序
L(H) = H + L(G) + L(X) + L(F) + GXF
L(G) = G + L(P) + P
L(X) = X + L(O) + O
L(F) = F + L(D) + L(E) + DE
L(P) = P + L(M) + L(N) + MN
L(D) = D + L(B) + L(C) + BC
L(E) = E + L(C) + A + CA
L(M) = M + L(F) + L(E) + FE
2) 合并:
L(H) = H + L(G) + L(X) + L(F) + GXF ====>HGPMXFDBECANO
L(G) = G + L(P) + P ====>GPMFDBECAN
L(X) = X + L(O) + O ====>XO
L(F) = F + L(D) + L(E) + DE ====>FDBECA
L(P) = P + L(M) + L(N) + MN ====>PMFDBECAN
L(D) = D + L(B) + L(C) + BC ====>DBCA
L(E) = E + L(C) + A + CA ====>ECA
L(M) = M + L(F) + L(E) + FE ====>MFDBECA
L(C) = C + L(A) ====>CA
L(N) = N ====>N
L(B) = B + L(A) + A ====>BA
类的MRO:H--->G--->P--->M--->X--->F--->D--->B--->E--->C--->A--->N--->O
四、super
1. 访问父类的初始化方法
这样子类和父类初始化方法中相同的代码可不必都写,直接用父类的就好
- class Base(object):
- 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().__init__(a, b, c)
- self.d = d
- f = Foo(1, 2, 3, 4)
- print(vars(f)) # {'a': 1, 'b': 2, 'c': 3, 'd': 4}
2. 实现子类方法调用父类(MRO)中的方法
- super().方法名():执行MRO中下一个方法
- super(类名,self).方法名():定位到该类,执行MRO中该类下一个类的方法
- class Biology(object):
- def move(self):
- print("----biology-----")
- class Animal(Biology):
- def move(self):
- print("-----Animal-----")
- class Cat(Animal):
- def move(self):
- super().move() # 找MRO中的下一个
- print("-----Cat-----")
- c = Cat()
- c.move()
- # 结果:
- # -----Animal-----
- # -----Cat-----
- class Biology(object):
- def move(self):
- print("----biology-----")
- class Animal(Biology):
- def move(self):
- print("-----Animal-----")
- class Cat(Animal):
- def move(self):
- super(Animal, self).move() # 定位到Animal,找Animal下一个
- print("-----Cat-----")
- c = Cat()
- c.move()
- # 结果:
- # ----biology-----
- # -----Cat-----
3. 应用
- class Init(object):
- def __init__(self, v):
- print("init")
- self.val = v
- class Add2(Init):
- def __init__(self, val):
- print("Add2")
- super(Add2, self).__init__(val)
- print(self.val)
- self.val += 2
-
-
- class Mult(Init):
- def __init__(self, val):
- print("Mult")
- super(Mult, self).__init__(val)
- self.val *= 5
-
-
- class HaHa(Init):
- def __init__(self, val):
- print("哈哈")
- super(HaHa, self).__init__(val)
- self.val /= 5
-
-
- class Pro(Add2,Mult,HaHa): #
- pass
-
-
- class Incr(Pro):
- def __init__(self, val):
- super(Incr, self).__init__(val)
- self.val += 1
- p = Incr(5)
- print(p.val) # Add2 Mult 哈哈 init 5.0 8.0
c = Add2(2)
print(c.val) # Add2 init 2 4
MRO:
1) Incr: Incr ---> Pro ---> Add2 ---> Mult ---> HaHa ---> Init
2) Add2: Add2 ---> Init