问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

怎么用好python中的多继承

发布网友 发布时间:2022-05-10 09:59

我来回答

2个回答

懂视网 时间:2022-05-10 14:20

class A(object): # A must be new-style class
 def __init__(self):
 print "enter A"
 print "leave A"
 
class B(C): # A --> C
 def __init__(self):
 print "enter B"
 super(B, self).__init__()
 print "leave B"

在我们的印象中,对于super(B, self).__init__()是这样理解的:super(B, self)首先找到B的父类(就是类A),然后把类B的对象self转换为类A的对象,然后“被转换”的类A对象调用自己的__init__函数。

有一天某同事设计了一个相对复杂的类体系结构(我们先不要管这个类体系设计得是否合理,仅把这个例子作为一个题目来研究就好),代码如下

代码段4:


class A(object):
 def __init__(self):
 print "enter A"
 print "leave A"
 
class B(object):
 def __init__(self):
 print "enter B"
 print "leave B"
 
class C(A):
 def __init__(self):
 print "enter C"
 super(C, self).__init__()
 print "leave C"
 
class D(A):
 def __init__(self):
 print "enter D"
 super(D, self).__init__()
 print "leave D"
 class E(B, C):
 def __init__(self):
 print "enter E"
 B.__init__(self)
 C.__init__(self)
 print "leave E"
 
class F(E, D):
 def __init__(self):
 print "enter F"
 E.__init__(self)
 D.__init__(self)
 print "leave F"

f = F() ,结果如下:

enter F enter E enter B leave B enter C enter D enter A leave A leave D leave C leave E enter D enter A leave A leave D leave F

明显地,类A和类D的初始化函数被重复调用了2次,这并不是我们所期望的结果!我们所期望的结果是最多只有类A的初始化函数被调用2次——其实这是多继承的类体系必须面对的问题。我们把代码段4的类体系画出来,如下图:

object
|
| A
| / |
B C D
/ |
E |
|
F

按我们对super的理解,从图中可以看出,在调用类C的初始化函数时,应该是调用类A的初始化函数,但事实上却调用了类D的初始化函数。好一个诡异的问题!

也就是说,mro中记录了一个类的所有基类的类类型序列。查看mro的记录,发觉包含7个元素,7个类名分别为:

F E B C D A object

  从而说明了为什么在C.__init__中使用super(C, self).__init__()会调用类D的初始化函数了。 ???

  我们把代码段4改写为:

代码段5:

class A(object):
 def __init__(self):
 print "enter A"
 super(A, self).__init__() # new
 print "leave A"
 
class B(object):
 def __init__(self):
 print "enter B"
 super(B, self).__init__() # new
 print "leave B"
 
class C(A):
 def __init__(self):
 print "enter C"
 super(C, self).__init__()
 print "leave C"
 
class D(A):
 def __init__(self):
 print "enter D"
 super(D, self).__init__()
 print "leave D"
 class E(B, C):
 def __init__(self):
 print "enter E"
 super(E, self).__init__() # change
 print "leave E"
 
class F(E, D):
 def __init__(self):
 print "enter F"
 super(F, self).__init__() # change
 print "leave F"

f = F(),执行结果:

enter F enter E enter B enter C enter D enter A leave A leave D leave C leave B leave E leave F

可见,F的初始化不仅完成了所有的父类的调用,而且保证了每一个父类的初始化函数只调用一次。

小结

  1. super并不是一个函数,是一个类名,形如super(B, self)事实上调用了super类的初始化函数,
产生了一个super对象;
  2. super类的初始化函数并没有做什么特殊的操作,只是简单记录了类类型和具体实例;
  3. super(B, self).func的调用并不是用于调用当前类的父类的func函数;
  4. Python的多继承类是通过mro的方式来保证各个父类的函数被逐一调用,而且保证每个父类函数
只调用一次(如果每个类都使用super);
  5. 混用super类和非绑定的函数是一个危险行为,这可能导致应该调用的父类函数没有调用或者一
个父类函数被调用多次。

一些更深入的问题:各位可以看到,print F.__mro__时发现里面元素的顺序是 F E B C D A object,这就是F的基类查找顺序,至于为什么是这样的顺序,以及python内置的多继承顺序是怎么实现的,这涉及到mro顺序的实现,

热心网友 时间:2022-05-10 11:28

怎么用好python中的多继承
可能你有C++的基础吧,C++确实可以不用带上this。
我把你的代码稍微改了一下,你可以分别看看cls1.n、cls2.n、self.n的输出。
class cls1:
n=3
class cls2(cls1):
def __init__(self,cls1=cls1):
cls2.n += 1
self.n += 2
print 'cls1.n:%s'%cls1.n
print 'cls2.n:%s'%cls2.n
print 'self.n:%s'%self.n

cls2()
print 'cls1.n:%s'%cls1.n
可以看出两个类和一个对象都可以在这里调用它们的n属性,如果只敲一个n别人读你的代码时就比较容易产生岐义,虽然少打了5个字符,但是不符合简单明确的pythonic哲学。
当然你也可以就认为python语法规则就是这么规定的。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
这种情况需要准备什么样的证据才能保证维权成功,关于个人知识产权方面... 侵犯著作权罪成立的条件是什么 网站被抄袭,怎么办?官网网页内容抄袭引发的法律问题 版权申请哪家性价比高? 著作权侵权损害如何赔偿 瓷砖划痕怎么处理方法 地板砖划痕怎么去除十种方法 关于梦幻西游转区的一些问题。懂的进。 茶叶泡水发苦的原因茶叶泡水发苦是什么原因 ...那又怎么样?从化学角度讲不也是那种分子起的作 linux日志文件是柱面吗? 惠普D7400连供墨盒清零步骤 linux中的.log日志文件可以随意删除吗?删除了对系统没有影响吧? Linux常用系统日志有啥?进程如何调度和控制?进程产生背景 中国有哪些较大的钢铁厂,各有怎样的规模? solidworks中装配体中怎么恢复外观移除? 怎么让solidworks默认零件颜色 solidworks零件默认颜色怎么恢复 请问SolidWorks零件 如何改变默认的白色外观 建下一个模型不用重复设置依然改变呢 solidworks去除材质后颜色还原 SolidWorks 界面变成这样,如何恢复原来的样子,就是刚安装是打开的那个样子 如何修改solidworks默认外观 急求,solidworks2016零件外观突然变了,请问怎么改回来??? 产业结构优化升级刻不容缓怎样解决脱实向虚和金融杠杆率高房地产泡沫的问题关 房地产杠杆影响是什么,国家如何宏观调控这一影响? 《中国家庭财富调查报告2019》发布显示房产占比居高不下,是什么原因? 咸肉海螺汤如何做? 冬瓜海螺汤的标准食谱 西瓜皮海螺汤怎么做 广东海螺汤的做法 python中的多继承常用吗? 快手号怎么上热门 “提拉米苏”什麽意思? 5d轻轻泥和3d超轻粘土哪个好?想捏生日蛋糕~最好保存时间久远的~谢谢~ 自制生日蛋糕的做法大全 10度到23度穿什么衣服 王者荣耀怎么设置微信好友不可见 乐虎塑料瓶是用什么材料做的 Python类多继承的具体机制怎样的 用塑料瓶自制气罐怎么做 染发膏弄到手上怎么办 读书郎学生平板电脑g100多少钱 平安保单贷款审批通过后几天下款? 英大元鸿B款两全保险怎么样 英大元鸿B重大疾病保险有买的吗 人寿保险最新2015年版重大疾病险 您好,我买了阳光人寿添富年年两全保险B款(分红型)每年交6000,已付一年,现想退保,大概能退多少钱啊! 吉祥两全保险b款(分红型) 分红 现代伊兰特变速箱发抖,怎么办? 别克君威弹簧胶垫需要更换吗