from threading import Thread class MyThread(Thread): def __init__(self, name): # 1、实现子类独有功能 print("子类线程 %s" % name) # 2、需要依赖父类方法完成其他功能 super().__init__(name=name)
多继承中使用 super
类图
实际代码
# 多继承 class Animal: def __init__(self, animalName): print(animalName, 'is an animal.') # Mammal 继承 Animal class Mammal(Animal): def __init__(self, mammalName): print(mammalName, 'is a mammal.') super().__init__(mammalName) # CannotFly 继承 Mammal class CannotFly(Mammal): def __init__(self, mammalThatCantFly): print(mammalThatCantFly, "cannot fly.") super().__init__(mammalThatCantFly) # CannotSwim 继承 Mammal class CannotSwim(Mammal): def __init__(self, mammalThatCantSwim): print(mammalThatCantSwim, "cannot swim.") super().__init__(mammalThatCantSwim) # Cat 继承 CannotSwim 和 CannotFly class Cat(CannotSwim, CannotFly): def __init__(self): print('I am a cat.'); super().__init__('Cat') # Driver code cat = Cat() print('') bat = CannotSwim('Bat') # 输出结果 I am a cat. Cat cannot swim. Cat cannot fly. Cat is a mammal. Cat is an animal. Bat cannot swim. Bat is a mammal. Bat is an animal.
好像挺奇怪的,从输出结果看,为什么 CannotSwim 类里面的 super().__init__() 调用的是 CannotFly 类里面的方法呢?不是应该调用 CannotSwim 的父类 Mamal 的方法吗?
灵魂拷问二:super 的执行顺序到底是什么?
- 其实 super() 并不一定调用父类的方法
- super() 是根据类的 MRO 方法搜索顺序来决定调用谁的
- super() 真正调用的是 MRO 中的下一个类,而不一定是父类
- 当然,这种情况只会出现在多继承
先来看看 Cat 的 MRO
print(Cat.__mro__)
(<class'__main__.Cat'>, <class'__main__.CannotSwim'>, <class'__main__.CannotFly'>, <class'__main__.Mammal'>, <class'__main__.Animal'>, <class'object'>)
从 Cat 的 MRO 可以看到
- CannotSwim 后面跟的是 CannotFly 而不是 Mamal
- 所以 CannotSwim 类里面的 super() 会调用 CannotFly 里面的方法
多继承的栗子二
实际代码
class A: def __init__(self): self.n = 2 def add(self, m): # 第四步 # 来自 D.add 中的 super # self == d, self.n == d.n == 5 print('self is {0} @AAA.add'.format(self)) self.n += m # d.n == 7 class C(A): def __init__(self): self.n = 4 def add(self, m): # 第三步 # 来自 B.add 中的 super # self == d, self.n == d.n == 5 print('self is {0} @CCC.add'.format(self)) # 等价于 suepr(C, self).add(m) # self 的 MRO 是 [D, B, C, A, object] # 从 C 之后的 [A, object] 中查找 add 方法 super().add(m) # 第五步 # d.n = 7 self.n += 4 # d.n = 11 class B(A): def __init__(self): self.n = 3 def add(self, m): # 第二步 # 来自 D.add 中的 super # self == d, self.n == d.n == 5 print('self is {0} @BBB.add'.format(self)) # self 的 MRO 是 [D, B, C, A, object] # 从 B 之后的 [C, A, object] 中查找 add 方法 # 从 C 找 add 方法 super().add(m) # 第六步 # d.n = 11 self.n += 3 # d.n = 14 class D(B, C): def __init__(self): self.n = 5 def add(self, m): # 第一步 print('self is {0} @DDD.add'.format(self)) # self 的 MRO 是 [D, B, C, A, object] # 从 D 之后的 [B, C, A, object] 中查找 add 方法 # 从 B 找 add 方法 super().add(m) # 第七步 # d.n = 14 self.n += 5 # self.n = 19 d = D() d.add(2) print(d.n)
先看看 D 类的 MRO
print(D.__mro__)
(<class'__main__.D'>, <class'__main__.B'>, <class'__main__.C'>, <class'__main__.A'>, <class'object'>)
输出结果
self is <__main__.D object at 0x10c14a190> @DDD.add self is <__main__.D object at 0x10c14a190> @BBB.add self is <__main__.D object at 0x10c14a190> @CCC.add self is <__main__.D object at 0x10c14a190> @AAA.add 19
调用顺序的确是 D、B、C、A
执行顺序
class D(B, C): class B(A): class C(A): class A: def add(self, m): def add(self, m): def add(self, m): def add(self, m): super().add(m) 1.---> super().add(m) 2.---> super().add(m) 3.---> self.n += m self.n += 5 <------6. self.n += 3 <----5. self.n += 4 <----4. <--| (14+5=19) (11+3=14) (7+4=11) (5+2=7)
执行顺序图
super() 的注意事项
https://www.cnblogs.com/poloyy/p/15236135.html