Python多继承以及MRO顺序

Python中的多继承问题:子类如何调用被重写的父类方法

以下的例子都是根据这个继承图来的
在这里插入图片描述

方式1.父类名.方法名(self,参数)

class Parent(object):
    def __init__(self,house):
        print("parent的init开始被调用")
        self.house = house
        print("parent的init结束被调用")

class Son1(Parent):
    def __init__(self,house,car1):
        print("son1的init开始被调用")
        self.car1 = car1
        Parent.__init__(self,house)  # 调用父类的被重写的方法
        print("son1的init结束被调用")

class Son2(Parent):
    def __init__(self,house,car2):
        print("son2的init开始被调用")
        self.car2 = car2
        Parent.__init__(self,house) # 调用父类的被重写的方法
        print("son2的init结束被调用")

class Grandson(Son1,Son2):
    def __init__(self,house,car1,car2):
        print("grandson的init开始被调用")
        Son1.__init__(self,house,car1) # 调用父类的被重写的方法
        Son2.__init__(self,house,car2) # 调用父类的被重写的方法
        print("grandson的init结束被调用")print("孙子的房子", gs.house)  # 孙子的房子 别墅
print("孙子的车子1", gs.car1)  # 孙子的车子1 大奔
print("孙子的车子2", gs.car2)  # 孙子的车子2 大众

调用顺序:

"""
grandson的init开始被调用
son1的init开始被调用
parent的init开始被调用
parent的init结束被调用
son1的init结束被调用
son2的init开始被调用
parent的init开始被调用
parent的init结束被调用
son2的init结束被调用
grandson的init结束被调用
"""

总结1:

该方式的好处:简洁明了,写了哪个父类名就去调用该父类的方法
导致问题:会造成父类的方法重复调用

方式2.super().方法名(参数)

class Parent(object):
    def __init__(self,house,*args,**kwargs):
        print("parent的init开始被调用")
        self.house = house
        print("parent的init结束被调用")

class Son1(Parent):
    def __init__(self,car1,house,*args,**kwargs):
        print("son1的init开始被调用")
        self.car1 = car1
        super().__init__(house,*args,**kwargs)
        print("son1的init结束被调用")

class Son2(Parent):
    def __init__(self,house,car2,*args,**kwargs):
        print("son2的init开始被调用")
        self.car2 = car2
        super().__init__(house)
        print("son2的init结束被调用")

class Grandson(Son1,Son2):
    def __init__(self,house,car1,car2):
        print("grandson的init开始被调用")
        super().__init__(house,car1,car2)
        print("grandson的init结束被调用")

使用super()的调用顺序是利用类里面的类.__mro__属性来查看下一个调用的顺序的,通过打印该属性,可以看到一个元组,如下

print(Grandson.__mro__) # 保证每个类只执行一次
(<class '__main__.Grandson'>, <class '__main__.Son1'>, <class '__main__.Son2'>, <class '__main__.Parent'>, <class 'object'>)

调用过程:当我们实例化一个Grandson类的对象时,会执行Grandson类下面的init方法,然后我们拿着当前的类名Grandson去找mro返回的元组中Grandson类名的下一位是谁,接下来便调用谁,而不是简单的看Grandson继承的顺序,故可以判断出super()将要调用的类是Son1,然后再Son1类后面是Son2类,接下来才是父类Parent,下面是具体的调用顺序

"""
grandson的init开始被调用
son1的init开始被调用
son2的init开始被调用
parent的init开始被调用
parent的init结束被调用
son2的init结束被调用
son1的init结束被调用
grandson的init结束被调用
"""

方式3:super(类名,self).方法(参数)

使用方法如下:

super(Son2,self).__init__(house,car1,car2)

与上个方法的区别
方式2的super里面未指定类名,故拿着super()所在的类名去mro的返回的元组中去找下一位,然后调用
而方式3由于指定了类名,故拿着指定的类名取mro返回的元组中去找下一位,然后调用

总结2

# 方式1
Son2.__init__(self, house, car2)
# 方式2
super(Son2, self).__init__(house, car1, car2)
# 方式3
super(Son2,self).__init__(house,car1,car2)

方式1直接用父类名的方法,造成父类方法的多次执行
super() 可以任意调用你要指定的父类,因此也是多继承时必须要全部传参的原因,父类只会被调用一次

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值