码迷,mamicode.com
首页 > 编程语言 > 详细

Python3 面向对象之:多继承

时间:2019-01-26 18:01:23      阅读:234      评论:0      收藏:0      [点我收藏+]

标签:foo   取出   最好   eth   gif   class   之间   准备   告诉   

多继承

技术分享图片
class ShenXian: # 神仙
    def fei(self):
        print("神仙都会?")
class Monkey: # 猴
    def chitao(self):
        print("猴?喜欢吃桃?")
class SunWukong(ShenXian, Monkey): # 孙悟空是神仙, 同时也是?只猴
    pass
sxz = SunWukong() # 孙悟空
sxz.chitao() # 会吃桃?
sxz.fei() # 会?
技术分享图片

  此时, 孙悟空是?只猴?, 同时也是?个神仙. 那孙悟空继承了这两个类. 孙悟空?然就可以执?这两个类中的?法. 多继承?起来简单. 也很好理解. 但是多继承中, 存在着这样?个问题. 当两个?类中出现了重名?法的时候. 这时该怎么办呢? 这时就涉及到如何查找?类?法的这么?个问题.即MRO(method resolution order) 问题. 在python中这是?个很复杂的问题. 因为在不同的python版本中使?的是不同的算法来完成MRO的.

这里需要补充一下python中类的种类(继承需要):

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

1经典类的多继承

虽然在python3中已经不存在经典类了. 但是经典类的MRO最好还是学?学. 这是?种树形结构遍历的?个最直接的案例. 在python的继承体系中. 我们可以把类与类继承关系化成?个树形结构的图. 来, 上代码:

技术分享图片 代码示例

对付这种mro画图就可以:

技术分享图片

继承关系图已经有了. 那如何进?查找呢? 记住?个原则. 在经典类中采?的是深度优先,遍历?案. 什么是深度优先. 就是?条路走到头. 然后再回来. 继续找下?个.

技术分享图片

图中每个圈都是准备要送鸡蛋的住址. 箭头和?线表?线路. 那送鸡蛋的顺序告诉你入?在最下?R. 并且必须从左往右送. 那怎么送呢?

技术分享图片

如图. 肯定是按照123456这样的顺序来送. 那这样的顺序就叫深度优先遍历. ?如果是142356呢? 这种被称为?度优先遍历. 好了. 深度优先就说这么多. 那么上?那个图怎么找的呢? MRO是什么呢? 很简单. 记住. 从头开始. 从左往右. ?条路跑到头, 然后回头. 继续?条路跑到头. 就是经典类的MRO算法. 

类的MRO: Foo-> H -> G -> F -> E -> D -> B -> A -> C. 你猜对了么?

2新式类的多继承

2.1 mro序列

MRO是一个有序列表L,在类被创建时就计算出来。
通用计算公式为:

mro(Child(Base1,Base2)) = [ Child ] + merge( mro(Base1), mro(Base2), [ Base1, Base2] )
(其中Child继承自Base1, Base2)

如果继承至一个基类:class B(A)
这时B的mro序列为

mro( B ) = mro( B(A) )
= [B] + merge( mro(A) + [A] )
= [B] + merge( [A] + [A] )
= [B,A]

 

如果继承至多个基类:class B(A1, A2, A3 …)
这时B的mro序列

mro(B) = mro( B(A1, A2, A3 …) )
= [B] + merge( mro(A1), mro(A2), mro(A3) ..., [A1, A2, A3] )
= ...

计算结果为列表,列表中至少有一个元素即类自己,如上述示例[A1,A2,A3]。merge操作是C3算法的核心。

2.2. 表头和表尾
表头:
  列表的第一个元素

表尾:
  列表中表头以外的元素集合(可以为空)

示例
  列表:[A, B, C]
  表头是A,表尾是B和C

2.3. 列表之间的+操作
+操作:

[A] + [B] = [A, B]
(以下的计算中默认省略)
---------------------

merge操作示例:

技术分享图片
如计算merge( [E,O], [C,E,F,O], [C] )
有三个列表 :  ①      ②          ③

1 merge不为空,取出第一个列表列表①的表头E,进行判断                              
   各个列表的表尾分别是[O], [E,F,O],E在这些表尾的集合中,因而跳过当前当前列表
2 取出列表②的表头C,进行判断
   C不在各个列表的集合中,因而将C拿出到merge外,并从所有表头删除
   merge( [E,O], [C,E,F,O], [C]) = [C] + merge( [E,O], [E,F,O] )
3 进行下一次新的merge操作 ......
--------------------- 
技术分享图片

技术分享图片

计算mro(A)方式:

技术分享图片
mro(A) = mro( A(B,C) )

原式= [A] + merge( mro(B),mro(C),[B,C] )

  mro(B) = mro( B(D,E) )
         = [B] + merge( mro(D), mro(E), [D,E] )  # 多继承
         = [B] + merge( [D,O] , [E,O] , [D,E] )  # 单继承mro(D(O))=[D,O]
         = [B,D] + merge( [O] , [E,O]  ,  [E] )  # 拿出并删除D
         = [B,D,E] + merge([O] ,  [O])
         = [B,D,E,O]

  mro(C) = mro( C(E,F) )
         = [C] + merge( mro(E), mro(F), [E,F] )
         = [C] + merge( [E,O] , [F,O] , [E,F] )
         = [C,E] + merge( [O] , [F,O]  ,  [F] )  # 跳过O,拿出并删除
         = [C,E,F] + merge([O] ,  [O])
         = [C,E,F,O]

原式= [A] + merge( [B,D,E,O], [C,E,F,O], [B,C])
    = [A,B] + merge( [D,E,O], [C,E,F,O],   [C])
    = [A,B,D] + merge( [E,O], [C,E,F,O],   [C])  # 跳过E
    = [A,B,D,C] + merge([E,O],  [E,F,O])
    = [A,B,D,C,E] + merge([O],    [F,O])  # 跳过O
    = [A,B,D,C,E,F] + merge([O],    [O])
    = [A,B,D,C,E,F,O]
--------------------- 
技术分享图片

 

结果OK. 那既然python提供了. 为什么我们还要如此?烦的计算MRO呢? 因为笔
试.......你在笔试的时候, 是没有电脑的. 所以这个算法要知道. 并且简单的计算要会. 真是项?
开发的时候很少有?这么去写代码.

这个说完了. 那C3到底怎么看更容易呢? 其实很简单. C3是把我们多个类产?的共同继
承留到最后去找. 所以. 我们也可以从图上来看到相关的规律. 这个要?家??多写多画图就
能感觉到了. 但是如果没有所谓的共同继承关系. 那?乎就当成是深度遍历就可以了

Python3 面向对象之:多继承

标签:foo   取出   最好   eth   gif   class   之间   准备   告诉   

原文地址:https://www.cnblogs.com/YZL2333/p/10324169.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!