1. 单独调用父类的方法

# coding=utf-8print("******多继承使用类名.__init__ 发生的状态******")
class Parent(object):def __init__(self, name):print('parent的init开始被调用')self.name = nameprint('parent的init结束被调用')class Son1(Parent):def __init__(self, name, age):print('Son1的init开始被调用')self.age = ageParent.__init__(self, name)print('Son1的init结束被调用')class Son2(Parent):def __init__(self, name, gender):print('Son2的init开始被调用')self.gender = genderParent.__init__(self, name)print('Son2的init结束被调用')class Grandson(Son1, Son2):def __init__(self, name, age, gender):print('Grandson的init开始被调用')Son1.__init__(self, name, age)  # 单独调用父类的初始化方法Son2.__init__(self, name, gender)print('Grandson的init结束被调用')gs = Grandson('grandson', 12, '男')
print('姓名:', gs.name)
print('年龄:', gs.age)
print('性别:', gs.gender)print("******多继承使用类名.__init__ 发生的状态******\n\n")

运行结果:

******多继承使用类名.__init__ 发生的状态******
Grandson的init开始被调用
Son1的init开始被调用
parent的init开始被调用
parent的init结束被调用
Son1的init结束被调用
Son2的init开始被调用
parent的init开始被调用
parent的init结束被调用
Son2的init结束被调用
Grandson的init结束被调用
姓名: grandson
年龄: 12
性别: 男
******多继承使用类名.__init__ 发生的状态******

2. 多继承中super调用有所父类的被重写的方法

print("******多继承使用super().__init__ 发生的状态******")
class Parent(object):def __init__(self, name, *args, **kwargs):  # 为避免多继承报错,使用不定长参数,接受参数print('parent的init开始被调用')self.name = nameprint('parent的init结束被调用')class Son1(Parent):def __init__(self, name, age, *args, **kwargs):  # 为避免多继承报错,使用不定长参数,接受参数print('Son1的init开始被调用')self.age = agesuper().__init__(name, *args, **kwargs)  # 为避免多继承报错,使用不定长参数,接受参数print('Son1的init结束被调用')class Son2(Parent):def __init__(self, name, gender, *args, **kwargs):  # 为避免多继承报错,使用不定长参数,接受参数print('Son2的init开始被调用')self.gender = gendersuper().__init__(name, *args, **kwargs)  # 为避免多继承报错,使用不定长参数,接受参数print('Son2的init结束被调用')class Grandson(Son1, Son2):def __init__(self, name, age, gender):print('Grandson的init开始被调用')# 多继承时,相对于使用类名.__init__方法,要把每个父类全部写一遍# 而super只用一句话,执行了全部父类的方法,这也是为何多继承需要全部传参的一个原因# super(Grandson, self).__init__(name, age, gender)super().__init__(name, age, gender)print('Grandson的init结束被调用')print(Grandson.__mro__)gs = Grandson('grandson', 12, '男')
print('姓名:', gs.name)
print('年龄:', gs.age)
print('性别:', gs.gender)
print("******多继承使用super().__init__ 发生的状态******\n\n")

运行结果:

******多继承使用super().__init__ 发生的状态******
(<class '__main__.Grandson'>, <class '__main__.Son1'>, <class '__main__.Son2'>, <class '__main__.Parent'>, <class 'object'>)
Grandson的init开始被调用
Son1的init开始被调用
Son2的init开始被调用
parent的init开始被调用
parent的init结束被调用
Son2的init结束被调用
Son1的init结束被调用
Grandson的init结束被调用
姓名: grandson
年龄: 12
性别: 男
******多继承使用super().__init__ 发生的状态******

注意:

  1. 以上2个代码执行的结果不同
  2. 如果2个子类中都继承了父类,当在子类中通过父类名调用时,parent被执行了2次
  3. 如果2个子类中都继承了父类,当在子类中通过super调用时,parent被执行了1次

3. 单继承中super


print("******单继承使用super().__init__ 发生的状态******")
class Parent(object):def __init__(self, name):print('parent的init开始被调用')self.name = nameprint('parent的init结束被调用')class Son1(Parent):def __init__(self, name, age):print('Son1的init开始被调用')self.age = agesuper().__init__(name)  # 单继承不能提供全部参数print('Son1的init结束被调用')class Grandson(Son1):def __init__(self, name, age, gender):print('Grandson的init开始被调用')super().__init__(name, age)  # 单继承不能提供全部参数print('Grandson的init结束被调用')gs = Grandson('grandson', 12, '男')
print('姓名:', gs.name)
print('年龄:', gs.age)
#print('性别:', gs.gender)
print("******单继承使用super().__init__ 发生的状态******\n\n")

总结

  1. super().__init__相对于类名.__init__,在单继承上用法基本无差
  2. 但在多继承上有区别,super方法能保证每个父类的方法只会执行一次,而使用类名的方法会导致方法被执行多次,具体看前面的输出结果
  3. 多继承时,使用super方法,对父类的传参数,应该是由于python中super的算法导致的原因,必须把参数全部传递,否则会报错
  4. 单继承时,使用super方法,则不能全部传递,只能传父类方法所需的参数,否则会报错
  5. 多继承时,相对于使用类名.__init__方法,要把每个父类全部写一遍, 而使用super方法,只需写一句话便执行了全部父类的方法,这也是为何多继承需要全部传参的一个原因

可以通过super()可以实现跳过一些通过会执行的步骤的功能。

小试牛刀(以下为面试题)

以下的代码的输出将是什么? 说出你的答案并解释。

class Parent(object):x = 1class Child1(Parent):passclass Child2(Parent):passprint(Parent.x, Child1.x, Child2.x)
Child1.x = 2
print(Parent.x, Child1.x, Child2.x)
Parent.x = 3
print(Parent.x, Child1.x, Child2.x)

答案, 以上代码的输出是:

1 1 1
1 2 1
3 2 3

使你困惑或是惊奇的是关于最后一行的输出是 3 2 3 而不是 3 2 1。为什么改变了 Parent.x 的值还会改变 Child2.x 的值,但是同时 Child1.x 值却没有改变?

这个答案的关键是,在 Python 中,类变量在内部是作为字典处理的。如果一个变量的名字没有在当前类的字典中发现,将搜索祖先类(比如父类)直到被引用的变量名被找到(如果这个被引用的变量名既没有在自己所在的类又没有在祖先类中找到,会引发一个 AttributeError 异常 )。

因此,在父类中设置 x = 1 会使得类变量 x 在引用该类和其任何子类中的值为 1。这就是因为第一个 print 语句的输出是 1 1 1。

随后,如果任何它的子类重写了该值(例如,我们执行语句 Child1.x = 2),然后,该值仅仅在子类中被改变。这就是为什么第二个 print 语句的输出是 1 2 1。

最后,如果该值在父类中被改变(例如,我们执行语句 Parent.x = 3),这个改变会影响到任何未重写该值的子类当中的值(在这个示例中被影响的子类是 Child2)。这就是为什么第三个 print 输出是 3 2 3。

继承不是复制而是指向

传智播客 多继承以及MRO顺序 学习笔记相关推荐

  1. 【传智播客郑州校区分享】数据库MYSQL笔记详解

    第1章 数据库 1.1 数据库概述 l 什么是数据库 数据库就是存储数据的仓库,其本质是一个文件系统,数据按照特定的格式将数据存储起来,用户可以对数据库中的数据进行增加,修改,删除及查询操作. l 什 ...

  2. 传智播客java怎么样_零基础学习java开发选择云和好还是传智播客好?

    和我撕或者喷我真的一点意义都没有,去不去培训班,去哪个培训班跟我没有半毛钱关系,你要说你自己就是这么与众不同又努力又是一个天才真能在那一大堆人之中脱颖而出,那么恭喜你你很牛逼,不需要特别告诉我我也没啥 ...

  3. 《传智播客.Net培训.net视频教程》(.net视频asp.net培训传智播客asp.net视频教程开放课程c#视频移动开发winform SQL ADO.Net HTML JavaScript

    本资源重要通知 2011年4月传智播客.Net培训-免费公开课现场视频 [重磅内容]微软移动开发介绍1-早起的鸟儿有食吃.rar 详情 53.2MB [重磅内容]微软移动开发介绍2-windows.p ...

  4. 我在传智播客上课的感受

    现在开始写博客,不过现在学习时间太紧,不知道能写多少呢 我在传智播客上课的感受,我是2.21班的,虽然上课没几天,但是还是挺累的,现在终于理解老师让开课前提前看视频的原因了,等着老师去讲知识与紧跟着老 ...

  5. tlias 教学过程_揭秘传智播客无缝切换线上教学,凭什么?

    在这个不平静的春节,新冠肺炎疫情牵动着全国人民的心.为了杜绝因人员聚集而引发的感染风险,全国各地启动延期开学.上班预案.面对当下线下实体班级教学困境,传智播客及时部署.全员出动,启动线上授课模式,学员 ...

  6. 陈力:传智播客古代 珍宝币 泡泡龙游戏开发第34讲:PHP 封装、继承、多态

    陈力:传智播客古代 珍宝币 泡泡龙游戏开发第34讲:PHP 封装.继承.多态 封装就是把抽象出的数据和对数据的操作封装在一起,通过public.  protected和private进行修饰.继承可以 ...

  7. php从入门到精通19天笔记,传智播客-PHP从入门到精通(19天)-video

    教程名称:传智播客-PHP从入门到精通(19天)-video 教程目录:├PHP传智社区学习资源.zip├下载必看 .txt├│  ├10目录访问权限(包括分布式权限).wmv│  ├11多站点配置. ...

  8. python基础教程视频(全13集)-Python基础视频教程(600集)【传智播客精品教程】...

    Python基础视频教程 初级共600节课 本套视频是传智播客紧抓未来最大趋势--人工智能,应运而生的一套Python入门视频教程,Python是学习人工智能的首选语言,而该视频是专门针对零基础的学员 ...

  9. 创智播客微服务_传智播客2018JavaEE IDEA版本

    资源内容: 传智播客2018JavaEE IDEA版本|____Java课件IDEA          |____主流框架          |____流行框架          |____Java基 ...

  10. Ubuntu16.04 ROS 深度学习_传智播客 智能机器人软件开发 学习路线图出炉!首发优惠!!...

    黑马程序员 微信号:heiniu526 传智播客旗下互联网资讯,学习资源免费分享平台 智能机器人软件工程师学习计划 很多朋友对机器人软件开发和人工智能感兴趣,不知道怎么学习,传智播客武汉校区在今年3月 ...

最新文章

  1. asio::write RuntimeError
  2. 【技术综述】人脸颜值研究综述
  3. Java中Map类型数据使用LinkedHashMap保留数据的插入顺序
  4. 制作alipay-sdk-java包到本地仓库
  5. 查看宝塔面板账号密码命令_宝塔面板升级到最新版图文教程
  6. 手把手教你制作好看实用的可视化驾驶舱
  7. java list交换_如何在JAVA中交换两个arraylist?
  8. Linux中安装JDK
  9. 小学多媒体计算机室管理计划,多媒体教室管理工作计划5篇
  10. ArcGIS 计算地类净面积工具
  11. AntDesign 表格设置背景色
  12. WY-2000B空气质量检测系统
  13. 互联网周刊:O2O商业模式剖析
  14. 计算机在课堂教学中的应用,计算机技术在课堂教学中的应用
  15. 工业4.0:换热站最酷设计—— Web SCADA 工业组态软件界面
  16. 百度文字识别(OCR)服务-傻瓜式
  17. [第3课] 象形统计图
  18. 硬盘安装FB{ZT}
  19. 一些免费和开源软件介绍
  20. java自行车租凭系统项目包_基于jsp的自行车租赁-JavaEE实现自行车租赁 - java项目源码...

热门文章

  1. VC++ DLL注入目标程序
  2. c++ 数组指针和指针数组
  3. python词云可视化视频_Python数据分析-可视化-wordcloud词云
  4. java虚拟机内存溢出的三个原因_java虚拟机学习(三) 内存溢出异常
  5. python实现概率论与数理统计_【总目录】——概率论与数理统计及Python实现
  6. java经纬度排序,elasticsearch搜索经纬度(lbs)_geo_distance距离排序实现方案
  7. canvas设置字体粗细用数字没效果_干货 | 用uni-app制作迷你PS小程序
  8. [实验]OSPF多区域互通---华为
  9. Linux系统启动流程和GRUB解释
  10. Angularjs的真分页,服务端分页,后台分页的解决方案