python3 类的多继承--super调用


概述

多继承的问题比较头疼,尤其是遇到了super。


一、super调用先检索兄弟类再检索父类

1. 测试super调用访问顺序

python3 中要理解super调用的逻辑,首先要理解什么是python的MRO (method resolution order),即在类的继承层次中检索方法的顺序。如图1所示,设计的类结构层次中,MyBook类有两个父类ToolBook和ScienceBook。ToolBook和ScienceBook为兄弟关系,它们有共同的子类和父类。从代码的输出结果可以看出MyBook类super调用先访问第一个父类ToolBook,然后ToolBook的super调用访问其兄弟类ScienceBook,最后ScienceBook的super调用访问其父类Book。

object
Book
ToolBook
ScienceBook
MyBook
图1 类的结构层次

代码块1

class Book(object):
    """
    书的基类
    """

    def __init__(self, book_id):
        self._id = book_id
        print('初始化Book')

    def print(self):
        """
        打印信息
        :return:
        """
        print('Book')
        print('id:{}'.format(self._id))


class ToolBook(Book):
    """
    工具类书
    """

    def __init__(self, book_id, name):
        print('开始初始化ToolBook')
        super(ToolBook, self).__init__(book_id)
        self._name = name
        print('初始化完成ToolBook')

    def print(self):
        """
        打印信息
        :return:
        """
        print('ToolBook')
        print('id:{}'.format(self._id))


class ScienceBook(Book):
    """
    科学类书
    """

    def __init__(self, book_id):
        print('开始初始化ScienceBook')
        super(ScienceBook, self).__init__(book_id)
        print('初始化完成ScienceBook')

    def print(self):
        """
        打印信息
        :return:
        """
        print('ScienceBook')
        print('id:{}'.format(self._id))


class MyBook(ToolBook, ScienceBook):
    """
    我感兴趣的书籍类型
    """

    def __init__(self, book_id, name):
        print('开始初始化MyBook')
        super(MyBook, self).__init__(book_id, name)
        print('初始化完成MyBook')

    def print(self):
        """
        打印信息
        :return:
        """
        print('MyBook')
        super().print()


if __name__ == '__main__':
    # 类的mro列表查询
    print('类MyBook的mro列表:{}'.format(MyBook.mro()))
    print('------------------')

    # 调用初始化函数
    python_book = MyBook('ASW123', 'python_book')
    print('------------------')
    # 类的函数调用
    python_book.print()
    print('------------------')

输出结果为:

类MyBook的mro列表:[<class '__main__.MyBook'>, <class '__main__.ToolBook'>, <class '__main__.ScienceBook'>, <class '__main__.Book'>, <class 'object'>]
------------------
开始初始化MyBook
开始初始化ToolBook
开始初始化ScienceBook
初始化Book
初始化完成ScienceBook
初始化完成ToolBook
初始化完成MyBook
------------------
MyBook
ToolBook
id:ASW123
------------------

2. 兄弟类的必要条件

将【代码块1】MyBook类修改为【代码块2】,取消对ScienceBook类的继承。那么此时ToolBook和ScienceBook不再是兄弟类,ToolBook的super调用不会再去检索ScienceBook。
将【代码块1】ScienceBook类修改为【代码块3】,ScienceBook不再从book类派生。那么此时ToolBook和ScienceBook不再是兄弟类,ToolBook的super调用不会再去检索ScienceBook。
由此可知,兄弟类必须有共同的父类和子类。此外,补充测试了给ScienceBook多加一个父类,以及增加另外一个子类,都不会影响兄弟类关系。
代码块2

class MyBook(ToolBook):
    """
    我感兴趣的书籍类型
    """

    def __init__(self, book_id, name):
        print('开始初始化MyBook')
        super(MyBook, self).__init__(book_id, name)
        print('初始化完成MyBook')

    def print(self):
        """
        打印信息
        :return:
        """
        print('MyBook')
        super().print()

输出结果为:

类MyBook的mro列表:[<class '__main__.MyBook'>, <class '__main__.ToolBook'>, <class '__main__.Book'>, <class 'object'>]
------------------
开始初始化MyBook
开始初始化ToolBook
初始化Book
初始化完成ToolBook
初始化完成MyBook
------------------
MyBook
ToolBook
id:ASW123
------------------

代码块3

class ScienceBook(object):
    """
    科学类书
    """

    def __init__(self, book_id):
        print('开始初始化ScienceBook')
        super(ScienceBook, self).__init__(book_id)
        print('初始化完成ScienceBook')

    def print(self):
        """
        打印信息
        :return:
        """
        print('ScienceBook')
        print('id:{}'.format(self._id))

输出结果:

类MyBook的mro列表:[<class '__main__.MyBook'>, <class '__main__.ToolBook'>, <class '__main__.Book'>, <class '__main__.ScienceBook'>, <class 'object'>]
------------------
开始初始化MyBook
开始初始化ToolBook
初始化Book
初始化完成ToolBook
初始化完成MyBook
------------------
MyBook
ToolBook
id:ASW123
------------------

二、super调用形式

  1. super(Type, 实例)
  2. super()
    第1种调用方式中实例必须是Type类型或其子类,第2种调用方式会将当前类指定为Type,并将self指定为实例。
    新增一个类如【代码块4】,super可以绕过直接基类访问间接基类。

代码块4

class YouBook(ToolBook, ScienceBook):
    """
    我感兴趣的书籍类型
    """

    def __init__(self, book_id):
        print('开始初始化YouBook')
        super(ScienceBook, self).__init__(book_id)
        print('初始化完成YouBook')

    def print(self):
        """
        打印信息
        :return:
        """
        print('YouBook')
        super().print()

参考文献

  1. python3菜鸟教程
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值