python super() 作用和原理
python 在类的继承中,当前类中如果方法与基类(父类)的方法一样,会覆盖基类的方法。
class Base(object): def run(self): print("Base start running~~") class Dog(Base): def run(self): print("Dog start running~~") if __name__ == "__main__": Dog().run() # 结果 Dog start running~~ Process finished with exit code 0
上面代码代码中,基类Base 并没有执行,但是有些时候,定义基类就是把共同的代码写在一起,在调用当前方法是,我们基类中已经实现的公共部分。
类的继承
- 经典类(classic class) 基类名.方法名(self, *args, **kwargs), python版本低于2.2
- 新式类(new-style class) super(当前类名, self).方法名(*args, **kwargs), python 版本大于2.2
1 class Base(object): 2 def run(self): 3 print("Now start running~~") 4 5 class Dog(Base): 6 def run(self): 7 Base.run(self) # 经典类继承 8 print("Dog start running~~") 9 10 if __name__ == "__main__": 11 Dog().run() 12 13 # 结果 14 Now start running~~ 15 Dog start running~~ 16 17 Process finished with exit code 0
当使用经典类继承时,Dog->Base->object 这种简单的继承顺序还可以,如果出现多重继承时,就会有下面的结果:
1 class Base(object): 2 def __init__(self): 3 print("进入Base 类") 4 5 6 class A(Base): 7 def __init__(self): 8 print("进入A 类") 9 Base.__init__(self) 10 11 12 class B(Base): 13 def __init__(self): 14 print("进入B 类") 15 Base.__init__(self) 16 17 18 class C(A, B): 19 def __init__(self): 20 print("进入C 类") 21 A.__init__(self) 22 B.__init__(self) 23 24 25 if __name__ == "__main__": 26 c = C()
运行结果:
1 进入C 类 2 进入A 类 3 进入Base 类 4 进入B 类 5 进入Base 类 6 7 Process finished with exit code 0
我们不难发现,执行顺序: C -> A -> Base -> B -> Base
是不是顺序有点蒙,我们理想状态的顺序难道不应该是: C -> A -> B -> Base (在继承多个类时,继承顺序从左往右依次继承)
如果按照理想状态运行应该怎么办, 我们就要用到 super 了。
super() 使用:
1 class Base(object): 2 def __init__(self): 3 print("进入Base 类") 4 5 6 class A(Base): 7 def __init__(self): 8 print("进入A 类") 9 super(A, self).__init__() # python2.7 的写法 10 11 12 class B(Base): 13 def __init__(self): 14 print("进入B 类") 15 super().__init__() 16 17 18 class C(A, B): 19 def __init__(self): 20 print("进入C 类") 21 super().__init__() # python3 继承的写法 22 23 24 if __name__ == "__main__": 25 c = C()
结果:
1 进入C 类 2 进入A 类 3 进入B 类 4 进入Base 类 5 6 Process finished with exit code 0
这样是不是就跟我们预想的一致了。
下面简单说一下super 是怎么运行的:
MRO
简单说一下 MRO(Method Resolution Order),中文可以叫做 方法解析顺序, 在方法调用时,需要对当前类以及基类进行搜索确定方法位置。
在程序中可以使用:
print(C.mro())
结果:
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>]
python MRO
- 经典类的深度遍历
- python2 新式类的预计算
- python3 新式类的C3线性化计算
python3 统一使用 C3 线性化算法,有兴趣的可以自行搜索。
小结
- 在super机制里可以保证公共父类仅被执行一次
- 执行的顺序,是按照MRO:方法解析顺序 进行的,执行完当前类按照mro 顺序执行下个类。
devops 开发小白,不喜勿喷
本文来自博客园,作者:Simba辛巴,转载请注明原文链接:https://www.cnblogs.com/spxinjie6/p/12877592.html