Method Resolution Order (MRO)

Arvind Padmanabhan

Indian Engineering

Design Forum


August 2013


http://iedf.in

Devopedia

 

 

February 2017

 

http://devopedia.org

The Linear Pattern

MRO

  • HappyPerson
  • FamilyPerson
  • Husband
  • Father
  • Professional
  • SelfEmployed
  • CharteredAccountant

Code

  • HappyPerson.mro()
  • HappyPerson.__mro__

 

The Diamond Pattern

MRO

  • Romantic19Novel
  • RomanticNovel
  • NineteenthCenturyNovel
  • Novel
  • Book

 

Code

  • Romantic19Novel.mro()
  • Romantic19Novel.__mro__

 

Summary

  • Multiple inheritance is not confusing if the call hierarchy is clearly understood:
    • Calls are depth first but where a common ancestor is involved, it is called as late as possible
  • Strictly speaking, everything in Python is a diamond pattern since all classes are based on object class, which is called last
  • Method mro() can be called on the class, not an object

Test Yourself

MRO

  • M
  • A
  • X
  • B
  • Y
  • Z
  • object

Code (Linear)

class Husband:
    def __init__(self):
        super().__init__()


class Father:
    def __init__(self):
        super().__init__()


class FamilyPerson(Husband, Father):
    def __init__(self):
        super().__init__()


class SelfEmployed:
    def __init__(self):
        super().__init__()


class CharteredAccountant:
    def __init__(self):
        super().__init__()


class Professional(SelfEmployed, CharteredAccountant):
    def __init__(self):
        super().__init__()


class HappyPerson(FamilyPerson, Professional):
    def __init__(self):
        super().__init__()


if __name__ == '__main__':
    hp = HappyPerson()
    print(HappyPerson.mro()) # list
    print(HappyPerson.__mro__) # tuple

    try:
        print(hp.mro()) # list
        print(hp.__mro__) # tuple
    except AttributeError:
        print('Cannot call MRO on an object. Call it on the class.')


Code (Diamond)

class Book:
    def __init__(self):
        super().__init__()


class Novel(Book):
    def __init__(self):
        super().__init__()


class MurderNovel(Novel):
    def __init__(self):
        super().__init__()


class RomanticNovel(Novel):
    def __init__(self):
        super().__init__()


class NineteenthCenturyNovel(Novel):
    def __init__(self):
        super().__init__()


class Romantic19Novel(RomanticNovel, NineteenthCenturyNovel):
    def __init__(self):
        super().__init__()


if __name__ == '__main__':
    mn = MurderNovel()
    r19n = Romantic19Novel()
    print(Romantic19Novel.mro()) # list
    print(Romantic19Novel.__mro__) # tuple

    try:
        print(r19n.mro()) # list
        print(r19n.__mro__) # tuple
    except AttributeError:
        print('Cannot call MRO on an object. Call it on the class.')


    # Another example
    class X: pass
    class Y: pass
    class Z: pass
    class A(X, Y): pass
    class B(Y, Z): pass
    class M(A, B, Z): pass
    print(M.mro())
Made with Slides.com