Python支持多继承,与C++一样都会出现一种问题:子类继承的多个父类又继承了同一个父类,这时就有可能会出现父类构造方法被调用多次的情况。关于这个问题,我找了一些资料,虽然没有亲自全部验证,这里我总结一下自己对这个问题的看法。

  Python和C++的关于这个问题的解决方案不太一样,当然Python还要看它的版本。

  C++用的方案是引入了虚继承的语法避免同一个类被构造了多次。

  Python用的方法是MRO(method resolution order,方法解析顺序) 。在在Python2.3之前,MRO的实现是基于DFS的,而在Python2.3以后MRO的实现是基于C3算法。找到的资料解释了一下更换算法的原因:

  为什么采用C3算法
  C3算法最早被提出是用于Lisp的,应用在Python中是为了解决原来基于深度优先搜索算法不满足本地优先级,和单调性的问题。
  本地优先级:指声明时父类的顺序,比如C(A,B),如果访问C类对象属性时,应该根据声明顺序,优先查找A类,然后再查找B类。
  单调性:如果在C的解析顺序中,A排在B的前面,那么在C的所有子类里,也必须满足这个顺序。
------------------------------新式类和旧式类中查找属性的顺序不同-------------------------------------
  在新式类中,查找一个要调用的函数或者属性的时候,是广度优先搜搜的。
  在旧式类当中,是深度优先搜索的。如下图所示:
  来一个例子:
  

 # -*- coding:utf-8 -*-

 class D(object):
def foo(self):
print "class D" class B(D):
pass class C(D):
def foo(self):
print "class C" class A(B, C):
pass f = A()
f.foo()
  例子中定义D类的时候,D是新式类,所以D的所有子类都是新式类。
  A的实例对象f在调用foo函数的时候,根据广度优先搜索原则,调用的是C类里面的foo函数。
  上面的代码输出class C
  如果定义D类的时候直接class D,而不是class D(object),那么上述代码就该输出class D了。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  如果我用的是super来解决多继承的初始化问题的话,那么到底是怎么初始化的呢?

  这是我一开始想到的一个问题:

  

 class A(object):
def __init__(self,a):
print a class B(object):
def __init__(self,a,b):
print a+b class C(A,B):
def __init__(self):
super(C,self).__init__(?) obj = C()

  第十一行的那个'?'的位置到底是填是什么进去才对呢?

  我一开始认为因为是多继承多以需要初始化父类的时候A,B都需要初始化,那么问题来了,super(C,self).__init__(?)怎么写?

  我试了一下:

  ① ? = 1      -->  输出1

  ② ? = 1,2       --> TypeError: __init__() takes exactly 2 arguments (3 given)

  定义C的时候改成class(B,A)

  ③ ? = 1      --> TypeError: __init__() takes exactly 3 arguments (2 given)

  ④ ? =1,2        --> 输出3

  再来看另一段代码:

 class A(object):
def func(self):
print 1 class B(object):
def __init__(self):
print 2 class C(A,B):
def __init__(self):
super(C,self).__init__() obj = C()
#The output is 3

  说明什么问题?在调用super(classname,self).__init__()的时候应该调用在继承的父类列表里面有实现__init__()这个方法而且最靠左边的那个父类的构造方法,而且这个__init__(?)的'?'一定要与父类列表的里面第一个有构造方法的父类的构造方法签名一样才可以。

  所以如果需要对所有父类都进行一遍初始化,还是使用类通过类名调用未绑定的初始化方法好(我说这一句话是因为我还不是很了解super)。

  说一下super的使用:

    super( classname,对象(一般情况是self) ) 返回的是一个super对象,你可以把它当作父类列表里面有实现__init__()这个方法而且最靠左边的那个父类的一个对象就可以了。

  参考文章地址:

    http://blog.csdn.net/imzoer/article/details/8737642

    http://blog.csdn.net/zyflying/article/details/8636006

Python - 对多继承以及super的一些了解的更多相关文章

  1. python's twenty day for me 继承 和 super()方法

    super(): 在单继承中就是单纯的寻找父类. 在多继承中就是根据子节点所在图 的mro顺序,找寻下一个类. 遇到多继承和super(): 对象.方法 1,找到这个对象对应的类. 2,将这个类的所有 ...

  2. 关于Python中的类普通继承与super函数继承

    关于Python中的类普通继承与super函数继承 1.super只能用于新式类 2.多重继承super可以保公共父类仅被执行一次 一.首先看下普通继承的写法 二.再看看super继承的写法 参考链接 ...

  3. Python大神必须掌握的技能:多继承、super和MRO算法

    本文主要以Python3.x为例讲解Python多继承.super以及MRO算法. 1. Python中的继承 任何面向对象编程语言都会支持继承,Python也不例外.但Python语言却是少数几个支 ...

  4. python继承之super

    super() 函数是用于调用父类(超类)的一个方法. super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO).重复调用( ...

  5. python语言中多继承中super调用所有父类的方法以及要用到的MRO顺序

    在python多继承中,利用super().父类方法,可以调用所有父类,从而在重写的状态下,再次对所有父类的调用! 例: print("******多继承使用super().__init__ ...

  6. python面向对象单继承,多继承和super()调用

    python 目录 python 1.继承 1.单继承 2.多继承 3.子类重写父类的同名属性和方法 核心点: 4.多层继承 5.super()的使用 1.继承 1.单继承 说明: 虽然子类没有定义_ ...

  7. python小兵 面向对象继承super和c3算法

    python多继承 在前面的学习过程中. 我们已经知道了Python中类与类之间可以有继承关系. 当出现了x是一种y的的时候. 就可以使⽤继承关系. 即"is-a" 关系. 在继承 ...

  8. [python] 在 python2和3中关于类继承的 super方法简要说明

    下面举一个例子,同样的代码使用 python2 和 python3 写的,大家注意两段程序中红色加粗的部分: python2的类继承使用super方法: #-*- coding:utf-8 -*- ' ...

  9. Python 中的继承、多态和封装

    涉及问题: Python 中如何实现多继承,会有什么问题? Python 中的多态与静态方法有什么区别? 答案要点如下: Python 中的继承,就是在定义类时,在括号中声明父类,简单示例如下: cl ...

随机推荐

  1. 慕课网4-2 编程练习:jQuery祖先后代选择器小案例

    4-2 编程练习 结合所学的祖先后代选择器,实现如下图所示效果 任务 (1)使用祖先后代选择器将第二段文字背景色变成红色 (2)使用jQuery的.css()方法设置样式,语法css('属性 '属性值 ...

  2. [NOIP2004]火星人

    Description 人类终于登上了火星的土地并且见到了神秘的火星人.人类和火星人都无法理解对方的语言,但是我们的科学家发明了一种用数字交流的方法.这种交流方法是这样的,首先,火星人把一个非常大的数 ...

  3. python生成excel文件

    2018-04-1919:04:25 测试代码如下: import openpyxl import datetime wb = openpyxl.Workbook() ws = wb.active w ...

  4. 用Python利用pyFirmata控制Arduino实现Blink

    2018-03-2809:20:44 arduino中有相应的库 1.安装pyFirmata包 pip install pyFirmata 在python2.7或python3.X下都可以执行. py ...

  5. 自定义样式 dialog

    自定义样式 dialog,可设置界面外点击屏幕外和返回键  是否消失 基本用法如下: CustomDialog.Builder customBuilder = new CustomDialog.Bui ...

  6. Android集成微信分享功能应用签名生成方法及分享不生效的问题

    通过友盟sdk集成微博.微信.qq等分享功能时,微博和qq很顺利,但在做微信集成时一直不成功.主要问题还是之前在微信开放平台申请创建移动应用时,对应用签名没有填写对,走了很多弯路现总结出来,加深记忆避 ...

  7. http链接中请求进行编码,Http请求

    如果参数中含有特殊字符&,则强制URL编码<br> http协议中参数的传输是"key=value"这种简直对形式的,如果要传多个参数就需要用“&”符号 ...

  8. 梦想CAD控件关于曲线问题

    IMxDrawCurve 接口 控件中的曲线接口,实现了曲线的相关操作,如求曲线的长度,最近点,面积,曲线上任一点在曲线上的长度 切向方向,曲线交点,坐标变换,打断,偏移,离散等功能. 一.返回曲线组 ...

  9. nginx反向代理与负载均衡讲解

    Nginx的代理功能与负载均衡功能是最常被用到的,关于nginx的基本语法常识与配置已在上篇文章中有说明,这篇就开门见山,先描述一些关于代理功能的配置,再说明负载均衡详细. Nginx代理服务的配置说 ...

  10. pycharm中将ui文件转换成py文件

    方法一:直接使用命令行 python -m PyQt5.uic.pyuic xx.ui -o xx.py 方法二:直接使用命令 先进到C:\python\pkgs\pyqt-5.9.2-py37h65 ...