前言
深入理解super()函数在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用super()函数来实现。
描述
- super() 函数是用于调用父类(超类)的一个方法。
- super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
- MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。
语法
super(type[, object-or-type])
参数:
- type – 类。
- object-or-type – 类,一般是 self
class A:
def __init__(self):
print("A")
class B(A):
def __init__(self):
print("B")
super().__init__() # 调用父类
if __name__ == '__main__':
b = B()
输出结果:
B
A # super调用父类输出 A
单继承方式
class Animal: # 创建动物类
"""动物类"""
def __init__(self, name): # 初始化方法
self.name = name
def eat(self): # 定义吃食物方法
print('%s正在吃食物' % self.name)
def play(self): # 定义玩耍方法
print('%s正在玩' % self.name)
def sleep(self): # 定义休息方法
print('%s正在休息' % self.name)
class Dog(Animal):
"""狗类"""
def __init__(self, name):
super().__init__(name) # 定义基类的初始化方法
print('这是一只%s' % self.name)
def eat(self): # 定义狗吃食物的方法
print('%s正在吃狗粮' % self.name)
def bark(self): # 定义狗叫的方法
print('%s会汪汪叫' % self.name)
dog = Dog('哈士奇') # 创建动物类的实例
dog.eat() # 调用吃食物的方法
dog.play() # 调用玩耍的方法
dog.bark() # 调用狗叫的方法
输出结果:
这是一只哈士奇
哈士奇正在吃狗粮
哈士奇正在玩
哈士奇会汪汪叫
根据运行结果看出第21行代码因为调用了super().init()方法,并传递了一个name参数。在Animal基类的__init__方法中,将name赋值给self.name。所以第22行代码会输出“这是一只哈士奇”。
多继承方式
class Food:
"""实物类"""
def __init__(self, name):
print('%s是食物' % name)
class Vegetables(Food):
"""蔬菜类"""
def __init__(self, Vname):
print('%s是蔬菜' % Vname)
super().__init__(Vname)
class Fruit(Food):
"""水果类"""
def __init__(self, Fname):
print('%s是水果' % Fname)
super().__init__(Fname)
class Tomato(Fruit, Vegetables):
"""西红柿类"""
def __init__(self):
print('西红柿即是蔬菜又是水果')
super().__init__('西红柿')
print(Tomato.__mro__) # MRO 列表顺序
tomato = Tomato() # 实例化西红柿类
输出结果:
(<class '__main__.Tomato'>, <class '__main__.Fruit'>, <class '__main__.Vegetables'>, <class '__main__.Food'>, <class 'object'>)
西红柿即是蔬菜又是水果
西红柿是水果
西红柿是蔬菜
西红柿是食物
根据运行结果可知:
- super函数执行顺序是根据MRO列表的顺序。
- super()其实和父类没有实质性的关联,只是在单继承的情况下,super()获得的类刚好是父类。
- super()等价于super(cls,inst)获得的是cls类在inst实例的MRO列表中的下一个类。
总结
- super()与父类没有实质性的关联
- super()获取的是MRO列表中下一个类