当前位置:天才代写 > tutorial > Python教程 > python 多担任详解

python 多担任详解

2017-11-02 08:00 星期四 所属: Python教程 浏览:55

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类和非绑定的函数是一个危险行为,这大概导致应该挪用的父类函数没有挪用可能一
      个父类函数被挪用多次。

#p#分页标题#e#

一些更深入的问题:列位可以看到,print F.__mro__时发明内里元素的顺序是 F E B C D A object,这就是F的基类查找顺序,至于为什么是这样的顺序,以及python内置的多担任顺序是怎么实现的,这涉及到mro顺序的实现,python 2.3今后的版本中是回收的一个叫做C3的算法,在下篇博客中举办先容。

 

    关键字:


天才代写-代写联系方式