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. bzoj 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生【dp】

    参考:http://hzwer.com/3917.html 好神啊 注意到如果分成n段,那么答案为n,所以每一段最大值为\( \sqrt{n} \) 先把相邻并且值相等的弃掉 设f[i]为到i的最小答 ...

  2. 在sql语句中使用关键字

    背景 开发过程中遇到了遇到了一句sql语句一直报错,看了一下字段名和表名都对应上了,但是还是一直报错 sql语句如下: update table set using = ""hh ...

  3. Java经典算法之折半查找(二分法)

    采用二分法时,数据应是有序并且不重复的 与小时候玩的猜数游戏是一样的,会让你猜一个他所想的1~100之间的数,当你猜了一个数后,他会告诉你三种选择中的一个,比他想的大,或小,或猜中了,为了能用最少的次 ...

  4. JavaScript编程艺术-第8章-8.6.1-显示“缩略词语表”

    8.6.1-显示“缩略词语表” ***代码亲测可用*** HTML: JS: ***end***

  5. ASP.Net 知识点总结(三)

    1.描述一下C#中索引器的实现过程,是否只能根据数字进行索引? 答:不是.可以用任意类型. 2.<%# %> 和 <% %> 有什么区别? 答:<%# %>表示绑定 ...

  6. C#封装访问修饰符

    C# 封装 封装 被定义为"把一个或多个项目封闭在一个物理的或者逻辑的包中".在面向对象程序设计方法论中,封装是为了防止对实现细节的访问. 抽象和封装是面向对象程序设计的相关特性. ...

  7. WebSphere设置会话超时时间

    WebSphere Application Server的会话超时时间可以在三个层面进行设置,分别为:应用程序服务器级别.应用程序级别和代码层面进行设置. 设置方式:应用程序级别级别和应用级别可以通过 ...

  8. .net引用System.Data.SQLite操作SQLite

    之所以要做这个笔记,是因为在.NET中使用System.Data.SQLite的时候,遇到了些问题,这些问题是相对于引用其他dll没有遇到过的,所以作个笔记,记录一下. 简单起见,首先建立一个控制台项 ...

  9. 全面学习ORACLE Scheduler特性(3)使用Programs

    二.使用Programs 在论坛中偶尔见过有人讨论如何在ORACLE中执行操作系统命令,或是ORACLE数据库外的应用.应该说在9i及之前的版本中,虽然说并非完全无法实现(其实还是有多种方式能够变相实 ...

  10. P1160 队列安排

    题目描述 一个学校里老师要将班上N个同学排成一列,同学被编号为1-N,他采取如下的方法: 1.先将1号同学安排进队列,这时队列中只有他一个人: 2.2-N号同学依次入列,编号为i的同学入列方式为:老师 ...