多继承以及MRO顺序【super().的使用】

多继承以及MRO顺序

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方法,只需写一句话便执行了全部父类的方法,这也是为何多继承需要全部传参的一个原因

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

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

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。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/456840.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

人工智能专业词汇集

最近看到一篇关于AI专业词汇总结的文章&#xff0c;感觉不错&#xff0c;分享一下。 对应的词汇项目地址为&#xff1a;https://github.com/jiqizhixin/Artificial-Intelligence-Terminology 本词汇库目前拥有的专业词汇共计 500 个&#xff0c;主要为机器学习基础概念和术语…

js 当前日期增加自然月

js 在日期不满足的情况下就会自动加1个月&#xff0c;比如在当前时间为3月31号&#xff0c;传入1&#xff0c;1两个参数&#xff0c;预期结果为2月29日&#xff0c;但是结果输出了3月2日。就是如果不满就会溢出到下个月&#xff0c;后来看了api发现了setMonth有两个方法&#x…

好雨云帮如何对接Git Server

前言 云帮目前支持对接GitLab、Gogs、Github,或者主流代码托管平台的公开项目&#xff0c;后期会考虑接入其他类型的Git服务。 私有云 GitLab是一个用于仓库管理系统的开源项目&#xff0c;私有云服务里使用比较多的自建Git服务。 对接GitLab 通过应用市场进行安装Gitlab 安装G…

Python 生成requirement 使用requirements.txt

python项目中必须包含一个 requirements.txt 文件&#xff0c;用于记录所有依赖包及其精确的版本号。以便新环境部署。requirements.txt可以通过pip命令自动生成和安装生成requirements.txt文件 pip freeze > requirements.txt安装requirements.txt依赖 pip install -r requ…

Source Insight上手教程

目录Project的建立和工作区域同步查看定义查找引用查找调用Source Insight常用快捷键 目录 最近刚参加工作&#xff0c;第一个任务就是查看项目的源码&#xff0c;熟悉代码结构。于是乎就简单学习了Source Insight。在这里就转载别人的文章当做自己的笔记&#xff0c;便于自己…

微信禁用右上角的分享按钮,WeixinJSBridge API以及隐藏分享的子按钮等菜单项

今天在做隐藏微信右上角的分享按钮 百度查到的一串代码&#xff0c;挺好用的 <!--禁用微信分享按钮--><script>function onBridgeReady() {WeixinJSBridge.call(hideOptionMenu);}if (typeof WeixinJSBridge "undefined") {if (document.addEventListen…

python2.7无法使用pip(安装easy_install)

python27和python36 共存时安装pip方法&#xff0c;解决python27文件夹下没有script文件方法 报错&#xff1a; D:\PYTHON2.7>python ez_setup.py Downloading http://pypi.python.org/packages/2.7/s/setuptools/setuptools-0.6c11-py2.7.egg Traceback (most recent call…

Codeforces 754E:Dasha and cyclic table

Codeforces 754E&#xff1a;Dasha and cyclic table 题目链接&#xff1a;http://codeforces.com/problemset/problem/754/E 题目大意&#xff1a;$A$矩阵&#xff08;$size(A)n \times m$&#xff0c;仅含a-z&#xff09;在整个平面做周期延拓&#xff0c;问$B$矩阵&#xff…

位运算中的左移和右移的计算详解

最近在学习javaScrapt&#xff0c;在学到位运算符这部分的时候&#xff0c;突然发现看不懂书上的例子了。经过查找资料后&#xff0c;发现了一遍不错的文章。分享一下&#xff1a; 正数的左移和右移 以3为例 3的二进制为 00000011 右移2位的时候将最右的11去掉左边补00结果…

AC日记——字符串P型编码 openjudge 1.7 31

31:字符串p型编码 总时间限制: 1000ms内存限制: 65536kB描述给定一个完全由数字字符&#xff08;0,1,2,…,9&#xff09;构成的字符串str&#xff0c;请写出str的p型编码串。例如&#xff1a;字符串122344111可被描述为"1个1、2个2、1个3、2个4、3个1"&#xff0c;因…

javascript中的define用法

文章目录1. AMD的由来2. AMD是什么3. AMD实例&#xff1a;如何定义一个模块4. 匿名模块5. 仅有一个参数的define6. Dojo中的AMD7. 结论最近由于工作需求只能快速学习JS&#xff0c;但在看代码的时候发现许多东西都有疑问比如说代码刚开始的define关键字的用法&#xff0c;刚好最…

解决:pip警告!DEPRECATION: The default format will switch to columns in the future.

pip警告&#xff01; DEPRECATION: The default format will switch to columns in the future. You can use --format(legacy|columns) (or define a format(legacy|columns) in your pip.conf under the [list] section) to disable this warning. pip升级到9.0.1后 查看pi…

PLSQL安装配置

&#xff08;1&#xff09;解压&#xff1a;plsql developer Oracle数据库开发工具首先确保有oracle数据库或者有oracle服务器&#xff0c;然后才能使用PLSQL Developer连接数据库。&#xff08;2&#xff09;工具---首选项---连接----输入OCI库&#xff08;设置之后不用再装or…

Mysql 学习笔记2

&#xff08;1&#xff09;MySQL查看表占用空间大小 //先进去MySQL自带管理库&#xff1a;information_schema //自己的数据库&#xff1a;dbwww58com_kuchecarlib //自己的表&#xff1a;t_carmodelparamvalue mysql> use information_schema; Database changed mysql&g…

python程序打包为exe可执行文件

大家都知道&#xff0c;Python是一种脚本语言&#xff0c;也就是解释型的语言&#xff0c;需要解释器来进行解释以后才可以执行&#xff0c;而Python源代码需要在Python虚拟机上面运行&#xff0c;但是我们做好的程序&#xff0c;不可能给用户使用的时候还让他安装一个Python环…

Backbone简介

1. 前言 本文的目的&#xff0c;是帮助大家快速理解掌握Backbone的使用&#xff0c;但它并不是API&#xff0c;因此我不会将每一个方法都详细地描述&#xff0c;但是我会告诉你如何学习它们。 这是一篇稍稍较长的技术文章&#xff0c;因为我想将我所了解的东西尽可能详细地分享…

使用Android Studio搭建Android集成开发环境

一、Android Studio简单介绍 2013年GoogleI/O大会首次发布了Android Studio IDE&#xff08;Android平台集成开发环境&#xff09;。它基于Intellij IDEA开发环境&#xff0c;旨在取代Eclipse和ADT&#xff08;Android开发者工具&#xff09;为开发者提供更好的开发工具。既然G…

[Oracle]UNIX与Windows 2000上Oracle的差异(I)

作者&#xff1a;Ian Adam & David Stien, SAIC Ltd 日期&#xff1a;19-Dec-2003 出处&#xff1a;http://www.dbanotes.net翻译&#xff1a;Fenng -----------------------------------------------------------------------------------------------------------------…

django2.x报错No module named 'django.core.urlresolvers'

解决方法就是: from django.urls import reverse 最近从django1.9迁移到django2.0中出现一个意外的报错&#xff1a; 这个报错的原因在stack overflow上有很直接的解释&#xff0c;但是百度上并没有直接的答案。 简单来说&#xff0c;原因就是&#xff1a;django2.0 把原来…

Underscore简介

5. Underscore.js Underscore封装了常用的JavaScript对象操作方法&#xff0c;用于提高开发效率。它本身与我们介绍的主题“Backbone”没有半毛钱的关系&#xff0c;因此你可以完全不理会“Backbone”的概念来学习它&#xff0c;或将它单独运用到任何一个页面。&#xff08;另外…