Method Resolution Order(MRO)

Classes

  • Classic classes

    Before Python 2.2

    Can not use super

    In [1]: class A():
       ...:     def __init__(self):
       ...:         self.a = 1
       ...:         
    
    In [2]: class B():
       ...:     def __init__(self):
       ...:         self.b = 2
       ...: 
    
    In [3]: class C(A, B):
       ...:     def __init__(self):
       ...:         super(C, self).__init__()
       ...:         
    
    In [4]: c = C()
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-4-607856e02023> in <module>()
    ----> 1 c = C()
    
    <ipython-input-3-fca959ece800> in __init__(self)
          1 class C(A, B):
          2     def __init__(self):
    ----> 3         super(C, self).__init__()
          4 
    
    TypeError: super() argument 1 must be type, not classobj
    
  • New style classes

    Since Python 2.2

    # Classic classes
    class A():
        pass
    
    # New style classes
    class A(object):
        pass
    

MRO

  • Old method resolution order

    Before Python 2.3

    depth first and then left to right
    
  • C3 method resolution order

    Since Python 2.3

    Can call instance.__mro__ & instance.mro()

    In [1]: class A(object):
       ...:     def __init__(self):
       ...:         self.a = 1
       ...:         
    
    In [2]: class B(object):
       ...:     def __init__(self):
       ...:         self.b = 2
       ...:         
    
    In [3]: class C(A, B):
       ...:     pass
       ...: 
    
    In [4]: C.__mro__
    Out[4]: (__main__.C, __main__.A, __main__.B, object)
    
    In [5]: C.mro()
    Out[5]: [__main__.C, __main__.A, __main__.B, object]
    

Multiple-inheritance

  • Classic classes

    • Parent Not Super & Child Not Super

      In [1]: class A():
         ...:     def __init__(self):
         ...:         self.a = 1
         ...:         
      
      In [2]: class B():
         ...:     def __init__(self):
         ...:         self.b = 2
         ...:         
      
      In [3]: class C(A, B):
         ...:     pass
         ...: 
      
      In [4]: c = C()
      
      In [5]: c.a
      Out[5]: 1
      
      In [6]: c.b
      ---------------------------------------------------------------------------
      AttributeError                            Traceback (most recent call last)
      <ipython-input-6-6be2854bea30> in <module>()
      ----> 1 c.b
      
      AttributeError: C instance has no attribute 'b'
      
    • Parent Not Super & Child Not Super

      In [1]: class A():
         ...:     def __init__(self):
         ...:         self.a = 1
         ...:         
      
      In [2]: class B():
         ...:     def __init__(self):
         ...:         self.b = 2
         ...:         
      
       In [3]: class C(A, B):
         ...:     def __init__(self):
         ...:         A.__init__(self)
         ...:         B.__init__(self)
         ...:
      
      In [4]: c = C()
      
      In [5]: c.a
      Out[5]: 1
      
      In [6]: c.b
      Out[6]: 2
      
  • New style classes

    • Parent Not Super

      In [1]: class A(object):
         ...:     def __init__(self):
         ...:         self.a = 1
         ...:         
      
      In [2]: class B(object):
         ...:     def __init__(self):
         ...:         self.b = 2
         ...:         
      
      In [3]: class C(A, B):
         ...:     pass
         ...: 
      # In [3]: class C(A, B):
      #   ...:     def __init__(self):
      #   ...:         super(C, self).__init__()
      #   ...:
      
      In [4]: c = C()
      
      In [5]: c.a
      Out[5]: 1
      
      In [6]: c.b
      ---------------------------------------------------------------------------
      AttributeError                            Traceback (most recent call last)
      <ipython-input-6-6be2854bea30> in <module>()
      ----> 1 c.b
      
      AttributeError: 'C' object has no attribute 'b'
      
    • One Parent Super

      In [1]: class A(object):
         ...:     def __init__(self):
         ...:         self.a = 1
         ...:         super(A, self).__init__()
         ...:         
      
      In [2]: class B(object):
         ...:     def __init__(self):
         ...:         self.b = 2
         ...:         
      
      In [3]: class C(A, B):
         ...:     def __init__(self):
         ...:         super(C, self).__init__()
         ...:         
      
      In [4]: c = C()
      
      In [5]: c.a
      Out[5]: 1
      
      In [6]: c.b
      Out[6]: 2
      
      In [7]: class D(B, A):
         ....:     def __init__(self):
         ....:         super(D, self).__init__()
         ....:         
      
      In [8]: d = D()
      
      In [9]: d.a
      ---------------------------------------------------------------------------
      AttributeError                            Traceback (most recent call last)
      <ipython-input-12-769f1638fd85> in <module>()
      ----> 1 d.a
      
      AttributeError: 'D' object has no attribute 'a'
      
      In [10]: d.b
      Out[10]: 2
      

Order

class A(object):  
    def __init__(self):  
        super(A, self).__init__()  
        print 'A!'

class B(object):  
    def __init__(self):  
        super(B, self).__init__()  
        print 'B!'

class AB(A, B):  
    def __init__(self):  
        super(AB, self).__init__()  
        print 'AB!'

class C(object):  
    def __init__(self):  
        super(C,  self).__init__()  
        print 'C!'

class D(object):  
    def __init__(self):  
        super(D, self).__init__()  
        print 'D!'

class CD(C, D):  
    def __init__(self):  
        super(CD, self).__init__()  
        print 'CD!'

class ABCD(AB, CD):  
    def __init__(self):  
        super(ABCD, self).__init__()  
        print 'ABCD!'

ABCD()

# D!
# C!
# CD!
# B!
# A!
# AB!
# ABCD!

References

[1] Docs@Python, 9. Classes - 9.5.1. Multiple Inheritance

[2] Releases@Python, The Python 2.3 Method Resolution Order

[3] zjm1126@StackOverflow, What does “mro()” do in Python?

results matching ""

    No results matching ""