设为首页 加入收藏

TOP

python学习笔记:第20天 多继承、MRO C3算法(一)
2018-11-14 20:08:27 】 浏览:224
Tags:python 学习 笔记 继承 MRO 算法

目录

一、多继承

之前已经学习过了继承,当出现了x是?种y的的时候,就可以使?继承关系,即"is-a" 关系。在继承关系中,?类?动拥有?类中除了私有属性外的其他所有内容,ython?持多继承,?个类可以拥有多个?类:

class A:
    def func1(self):
        print('我是A类的func1')
        
class B:
    def func2(self):
        print('我是B类的func2')
        
class C(A, B):
    def func3(self):
        print('我是C类的func3')
        
c = C()
c.func1()
c.func2()
c.func3()

# 结果:
# 我是A类的func1
# 我是B类的func2
# 我是C类的func3

多继承用起来虽然很简单,但是它也会带来一些问题,当两个?类中出现了重名?法的时候,即出现了二义性,这时该怎么办呢?这时就涉及到如何查找?类?法的这么?个问题,即MRO(method resolution order) 问题,在python中不同版本的MRO查找父类的顺序也不一样:

  • python2中存在这两种类:
    • ?个叫经典类. 在python2.2之前,?直使?的是经典类,经典类在基类的根如果什么都不写,表?继承xxx.
    • ?个叫新式类. 在python2.2之后出现了新式类,新式类的特点是基类的根是object
  • python3
    • python3中使?的都是新式类. 如果基类谁都不继承. 那这个类会默认继承object

二、旧式类的MRO

旧式类的MRO是通过数型结构的深度优先遍历的顺序查找,深度优先遍历的查找顺序如下:

两种继承模式在DFS下的优缺点。

  • 第一种通常称为正常继承模式,两个互不相关的类的多继承,这种情况DFS顺序正常,不会引起任何问题;

  • 第二种,棱形继承模式,存在公共父类(D)的多继承这种情况下DFS必定经过公共父类(D),这时候想想,如果这个公共父类(D)有一些初始化属性或者方法,但是子类(C)又重写了这些属性或者方法,那么按照DFS顺序必定是会先找到D的属性或方法,那么C的属性或者方法将永远访问不到,导致C只能继承无法重写(override)。

旧式类MRO的查找只需要记住一个原则:在经典类中采?的是深度优先遍历?案. 什么是深度优先. 就是?条路走到头. 然后再回来. 继续找下?个

三、新式类的MRO

python中的新式类的MRO是采?的C3算法来完成的。

c3算法很简单,就看你的代码就够了,不需要去画图。计算方法和公式如下:

L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN)       # 以下的merge函数由L代替(只是书写方式不一样)
L[object] = object
def merge(seqs):
    print '\n\nCPL[%s]=%s' % (seqs[0][0],seqs),
    res = []; i=0
    while 1:
      nonemptyseqs=[seq for seq in seqs if seq]
      if not nonemptyseqs: return res
      i+=1; print '\n',i,'round: candidates...',
      for seq in nonemptyseqs: # find merge candidates among seq heads
          cand = seq[0]; print ' ',cand,
          nothead=[s for s in nonemptyseqs if cand in s[1:]]
          if nothead: cand=None #reject candidate
          else: break
      if not cand: raise "Inconsistent hierarchy"
      res.append(cand)
      for seq in nonemptyseqs: # remove cand
          if seq[0] == cand: del seq[0]

def mro(C):
    "Compute the class precedence list (mro) according to C3"
    return merge([[C]]+map(mro,C.__bases__)+[list(C.__bases__)])

以上代码摘自于python官方文档,对于python的MRO C3算法感兴趣的朋友可以看先这里:Python官方对MRO的说明

先看个例子:

class A:pass
class B:pass
class C:pass
class E(A,B):pass
class F(B,C):pass
class G(E,F):pass

# 求G的MRO查找顺序?

最终结果为:GEAFBC,最终我们可以使?class_name.__mro__或者class_name.mro()获取到类的MRO信息。

我们再来看一个复杂的例子:

class A:pass
class B(A):pass
class C(A):pass
class D(B, C):pass
class E(C, A):pass
class F(D, E):pass
class M(F, E):pass
class N:pass
class P(M,N):pass
class G(P):pass
class O:pass
class X(O):pass
class H(G, X, F):pass

# 求H的MRO?

照之前的方法处理,可以得到如下结果:


L(H) = H + L(G) + L(X) + L(F) + (GXF)   # ==> H + (GPMFDBECAN) +  (XO) + (FDBECA) + (GXF)       # 得到最终的公式,
                                    (FDBECAN) + (XO) + (FDBECA) + (XF) = HGPM                   # 先提取出HGPMX
                                    (FDBECAN) + (O) + (FDBECA) + (F) = HGPMX                    # 再提取出X
                                    (DBECAN) + (O) + (DBECA) = HGPMXF                           # 再提取F
                                                ====>  HGPM XFDB ECANO                          # 最终得到结果

L(G) = G + L(P) + P                     # ==> G + (PMFDBECAN) + P = GPMFDBECAN
L(X) = X + L(O) + O                     # ==> X + (O) + O = XO
L(P) = P + L(M) + L(N) + (MN)           # ==> P + (MFDBECA) + (N) + (MN) = PMFDBECAN
L(M) = M + L(F) + L(E) + (FE)           # ==> M + (FDBECA) + (ECA) + (FE) = MFDBECA

L(F) = F + L(D) + L(E) + (DE)           # ==> F + (DBCA) + (ECA) + (DE) = FDBECA
L(E) = E + L(C) + L(A) + (CA)           # ==> E + (CA) + A + (CA) = ECA

L(D) = D + L(B) + L(C) + (BC)           # ==> D + (BA) + (CA) + (BC) = DBCA
L(B) = B + L(A) + A                     # BA
L(C) = C + L(A) + A                     # CA
L(A) = A

结果如下:

总结一下:C3是把我们多个类产?的共同继承留到最后去找. 所以. 我们也可以从图上来看到相关的规律. 这个要?家??多写多画图就能感觉到了. 但是如果没有所谓的共同继承关系. 那?乎就当成是

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇【Python3爬虫】拉勾网爬虫 下一篇django配置发送邮箱

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目