python记录day_20 多继承
多继承
继承: x是一种y的时候.可以使用继承关系。是"is a"的关系
在python中,支持多继承,一个类可以拥有多个父类。但是多继承中, 存在着这样一个问题,当两个父类中出现了重名方法的时候该怎么办呢? 这时就涉及到如何查找父类方法的问题。即mro(method resolution order) 问题。在python中这是个很复杂的问题,因为在不同的 python版本中使用的是不同的算法来完成mro的。
经典类计算mro用的是深度优先的遍历算法,而新式类的mro用的是c3算法
##对于经典类和新式类的区分(已经成为过去时了):
在python2中
没有显式声明继承object类的类及其子类,被称为经典类
有显式声明继承object类的类及其子类,被称为新式类,新式类是在python2.2之后才出现的,在此之前都是用的经典类
python3中默认都继承了object类,所以python3中都是新式类。
#经典类的mro
深度优先:从左子树开始,右子树结束,一条道走到黑
遍历结果: foo-> h -> g -> f -> e -> d -> b -> a -> c
#新式类的mro
新式类的mro是采用的c3算法来完成的,c3的核心是merge
先拆分后合并,合并用merge
merge原则:拿每一项的头和后一项的身体比较,如果出现了,就跳过,从后一项的头继续去比较,如果不出现就拿出这个元素,并删除这个和其他列表中的元素,merge一次后继续从头开始。
1 class d(o): 2 pass 3 class f(o): 4 pass 5 class c(d,f): 6 pass 7 8 # c的mro 9 l[c] = c + merge(do,fo,df) #d 和后边其他项的身体都不同,d出来,删除d 10 = c + d + merge(o,fo,f) #o和第二项的身体相同,o跳过,f和后边其他项的身体都不同,f出来,删除f 11 = c + d + f + merge(o,o) 12 = c d f o
1 class a: 2 pass 3 class b(a): 4 pass 5 class c(a): 6 pass 7 class d(b, c): 8 pass 9 class e(c, a): 10 pass 11 class f(d, e): 12 pass 13 class m(f, e): 14 pass 15 class n: 16 pass 17 class p(m,n): 18 pass 19 class g(p): 20 pass 21 class o: 22 pass 23 class x(o): 24 pass 25 class h(g, x, f): 26 pass 27 28 ''' 29 拆分:(注意拆分时在最后面加上所有的子类名) 30 l(h) = h + l(g) + l(x) + l(f) + gxf # 合并: h + gpmfdbecan + x + fdbeca + gxf =hgpmxfdbecan 31 32 l(g) = g + l(p) + p # g + pmfdbecan + p = gpmfdbecan 33 l(x) = x + l(o) + o # x + o + o =xo 34 l(f) = f + l(d) + l(e) + de # f + dbca + eca + de = fdbeca 35 36 37 l(p) = p + l(m) + l(n) + mn # p + mfdbeca + n +mn = pmfdbecan 38 l(d) = d + l(b) + l(c) + bc # 合并: d + ba +ca + bc = dbca 39 l(e) = e + l(c) + l(a) + ca # 合并: e + ca + a + ca = eca 40 41 l(m) = m + l(f) + l(e) + fe # 合并: m + fdbeca + eca + fe = mfdbeca 42 43 ''' 44 45 print(h.__mro__) 46 结果: 47 (<class '__main__.h'>, <class '__main__.g'>, <class '__main__.p'>, <class '__main__.m'>, <class '__main__.x'>, <class '__main__.f'>, <class '__main__.d'>, <class '__main__.b'>, <class '__main__.e'>, <class '__main__.c'>, <class '__main__.a'>, <class '__main__.n'>, <class '__main__.o'>, <class 'object'>)
##
还有一种计算mro的方法是通过画图,把继承关系看做一个有向无环进行遍历也能得到正确结果(遍历规则:找入度为0的节点,有多个时,按从左往右的顺序),相对而言这种方式更便捷,详细见下面文章
关于python中mro的深度解释
http://python.jobbole.com/85685/
##super()
记住super查找的是mro列表中的下一个