欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python记录day_20 多继承

程序员文章站 2022-03-25 20:59:44
多继承 继承: x是一种y的时候.可以使用继承关系。是"is a"的关系 在python中,支持多继承,一个类可以拥有多个父类。但是多继承中, 存在着这样一个问题,当两个父类中出现了重名方法的时候该怎么办呢? 这时就涉及到如何查找父类方法的问题。即MRO(method resolution orde ......

多继承

继承: x是一种y的时候.可以使用继承关系。是"is a"的关系

在python中,支持多继承,一个类可以拥有多个父类。但是多继承中, 存在着这样一个问题,当两个父类中出现了重名方法的时候该怎么办呢? 这时就涉及到如何查找父类方法的问题。即mro(method resolution order) 问题。在python中这是个很复杂的问题,因为在不同的 python版本中使用的是不同的算法来完成mro的。

经典类计算mro用的是深度优先的遍历算法,而新式类的mro用的是c3算法

 

##对于经典类和新式类的区分(已经成为过去时了):

在python2中

没有显式声明继承object类的类及其子类,被称为经典类

有显式声明继承object类的类及其子类,被称为新式类,新式类是在python2.2之后才出现的,在此之前都是用的经典类

python3中默认都继承了object类,所以python3中都是新式类

 

#经典类的mro

深度优先:从左子树开始,右子树结束,一条道走到黑

python记录day_20   多继承

遍历结果: 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
python记录day_20   多继承
 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题

##

还有一种计算mro的方法是通过画图,把继承关系看做一个有向无环进行遍历也能得到正确结果(遍历规则:找入度为0的节点,有多个时,按从左往右的顺序),相对而言这种方式更便捷,详细见下面文章

关于python中mro的深度解释

http://python.jobbole.com/85685/

 

##super()

记住super查找的是mro列表中的下一个