Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Method Resolution Order in Python

Method Resolution Order in Python

Imagine implementing inheritance in a programming language. At first, it looks like all the methods and attributes will be inherited by the child class. While it works for the majority of scenarios, as soon as we hit multiple-inheritance, deciding what method/attribute will take precedence, becomes a daunting task.

This is also known as the diamond problem. While some languages use an algorithm such as right-first-depth-first search to solve this, Python 2 used Depth-first from Left to Right (DLR) and Python3 uses C3 Linearization Algorithm. Getting hold of this information will help you not succumbing to the common pitfalls with the arrangement of name lookups in a class hierarchy.

MRO (Method Resolution Order) defines the class search path for linearizing the class ancestor tree. We’ll also have a look at how C3 algorithm is monotonic as it guarantees that base class declaration is preserved and subclasses appear before base classes. We’ll further explore MRO using __bases__, __base__, __mro__ magic methods.

Sanyam Khurana

October 18, 2022
Tweet

More Decks by Sanyam Khurana

Other Decks in Programming

Transcript

  1. Method Resolution Order (MRO) in Python Sanyam Khurana DjangoCon US

    2022 | San Diego, CA, USA ErSanyamKhurana CuriousLearner
  2. ErSanyamKhurana CuriousLearner def __who_am_i__(): • One of You - A

    part of the community • Masters in CS (ML Specialization) from Georgia Tech. • Maintainer Django Phone Verify, Django-sites, DjangoProject.com • Individual member of DSF (Django Software Foundation) • Bug-Triager for CPython • Contributor to Mozilla Firefox Browser 👋
  3. ErSanyamKhurana CuriousLearner Goal of the talk 🤔 • Understand how

    & why MRO evolved. • Do not ever get tripped by Multiple inheritance. • Always use inheritance in a more meaningful way — going from specialized to generic classes.
  4. ErSanyamKhurana CuriousLearner Multiple Inheritance 👪 • Languages like Java /

    C# do not support Multiple Inheritance. • They don’t want to get caught by the Diamond problem. • Python solves this problem!
  5. ErSanyamKhurana CuriousLearner The Solution ✅ Method Resolution Order (MRO) de

    fi nes the class search path used by Python to search for the right attribute / method to use in classes having multi-inheritance.
  6. ErSanyamKhurana CuriousLearner The Solution ✅ Method Resolution Order (MRO) de

    fi nes the class search path used by Python to search for the right attribute / method to use in classes having multi-inheritance.
  7. ErSanyamKhurana CuriousLearner The Solution ✅ Old MRO New MRO DLR

    Algorithm (Depth-First Left to Right) Used prior to Python 2.2 Used in Old style classes Two Algorithms to fi nd MRO
  8. ErSanyamKhurana CuriousLearner The Solution ✅ Old MRO New MRO DLR

    Algorithm (Depth-First Left to Right) Used prior to Python 2.2 Used in Old style classes C3 Linearization Algorithm (Searching the “Good Heads”) Introduced in Python 2.3 Used in New style classes Two Algorithms to fi nd MRO
  9. ErSanyamKhurana CuriousLearner The Solution ✅ Old Style Classes Uses old

    MRO New Style Classes Base classes inherits from object Uses C3 Linearization Algorithm
  10. ErSanyamKhurana CuriousLearner The Solution ✅ Old Style Classes Uses old

    MRO New Style Classes Base classes inherits from object Uses C3 Linearization Algorithm
  11. ErSanyamKhurana CuriousLearner The Solution ✅ Old Style Classes Uses old

    MRO New Style Classes Base classes inherits from object Uses C3 Linearization Algorithm
  12. ErSanyamKhurana CuriousLearner Gotcha 👌 If you’re using old-style classes in

    Python >= 2.3 and Python < 3, they’ll be using the DLR (Old-MRO Algorithm) Only new style classes on Python >= 2.3 will be using C3 Linearization algorithm
  13. ErSanyamKhurana CuriousLearner Old MRO: DLR on Diamond problem A B

    D C Rule: Depth fi rst, left to right D Look in class D If not found in D, look at fi rst parent of D, i.e. B If not found in B, look at it’s parent, A If not found, look at B’s other parents If not found, then look at D’s other parents I.e. C
  14. ErSanyamKhurana CuriousLearner Old MRO: DLR on Diamond problem A B

    D C Rule: Depth fi rst, left to right D B Look in class D If not found in D, look at fi rst parent of D, i.e. B If not found in B, look at it’s parent, A If not found, look at B’s other parents If not found, then look at D’s other parents I.e. C
  15. ErSanyamKhurana CuriousLearner Old MRO: DLR on Diamond problem A B

    D C Rule: Depth fi rst, left to right D B A Look in class D If not found in D, look at fi rst parent of D, i.e. B If not found in B, look at it’s parent, A If not found, look at B’s other parents If not found, then look at D’s other parents I.e. C
  16. ErSanyamKhurana CuriousLearner Old MRO: DLR on Diamond problem A B

    D C Rule: Depth fi rst, left to right D B A Look in class D If not found in D, look at fi rst parent of D, i.e. B If not found in B, look at it’s parent, A If not found, look at B’s other parents If not found, then look at D’s other parents I.e. C
  17. ErSanyamKhurana CuriousLearner Old MRO: DLR on Diamond problem A B

    D C Rule: Depth fi rst, left to right D B A C Look in class D If not found in D, look at fi rst parent of D, i.e. B If not found in B, look at it’s parent, A If not found, look at B’s other parents If not found, then look at D’s other parents I.e. C
  18. ErSanyamKhurana CuriousLearner Old MRO: DLR on Diamond problem A B

    D C Rule: Depth fi rst, left to right D B A C A Look in class D If not found in D, look at fi rst parent of D, i.e. B If not found in B, look at it’s parent, A If not found, look at B’s other parents If not found, then look at D’s other parents I.e. C
  19. ErSanyamKhurana CuriousLearner Old MRO: DLR on Diamond problem A B

    D C Rule: Depth fi rst, left to right D B A C Look in class D If not found in D, look at fi rst parent of D, i.e. B If not found in B, look at it’s parent, A If not found, look at B’s other parents If not found, then look at D’s other parents I.e. C (Remove duplicates from end)
  20. ErSanyamKhurana CuriousLearner Monotonicity A MRO is monotonic when the following

    is true: if C1 precedes C2 in the linearization(class precedence list) of C, then C1 precedes C2 in the linearization of any subclass of C.
  21. ErSanyamKhurana CuriousLearner Monotonicity MRO[A] = A A B D C

    if C1 precedes C2 in the linearization(class precedence list) of C, then C1 precedes C2 in the linearization of any subclass of C.
  22. ErSanyamKhurana CuriousLearner Monotonicity MRO[A] = A MRO[B] = B A

    B D C if C1 precedes C2 in the linearization(class precedence list) of C, then C1 precedes C2 in the linearization of any subclass of C.
  23. ErSanyamKhurana CuriousLearner Monotonicity MRO[A] = A MRO[B] = B MRO[C]

    = C B A A B D C if C1 precedes C2 in the linearization(class precedence list) of C, then C1 precedes C2 in the linearization of any subclass of C.
  24. ErSanyamKhurana CuriousLearner Monotonicity MRO[A] = A MRO[B] = B MRO[C]

    = C B A MRO[D] = D B C A B D C if C1 precedes C2 in the linearization(class precedence list) of C, then C1 precedes C2 in the linearization of any subclass of C.
  25. ErSanyamKhurana CuriousLearner Monotonicity MRO[A] = A MRO[B] = B MRO[C]

    = C B A MRO[D] = D B C B A A B D C if C1 precedes C2 in the linearization(class precedence list) of C, then C1 precedes C2 in the linearization of any subclass of C.
  26. ErSanyamKhurana CuriousLearner Monotonicity MRO[A] = A MRO[B] = B MRO[C]

    = C B A MRO[D] = D B C B A A B D C if C1 precedes C2 in the linearization(class precedence list) of C, then C1 precedes C2 in the linearization of any subclass of C.
  27. ErSanyamKhurana CuriousLearner Monotonicity MRO[A] = A MRO[B] = B MRO[C]

    = C B A MRO[D] = D B C B A A B D C if C1 precedes C2 in the linearization(class precedence list) of C, then C1 precedes C2 in the linearization of any subclass of C. B is parent of C, Yet appears before C in MRO of D 😱
  28. ErSanyamKhurana CuriousLearner Monotonicity MRO[A] = A MRO[B] = B MRO[C]

    = C B A MRO[D] = D B C B A A B D C if C1 precedes C2 in the linearization(class precedence list) of C, then C1 precedes C2 in the linearization of any subclass of C. Non-montonic 😱
  29. ErSanyamKhurana CuriousLearner C3 Linearization Algorithm C3 superclass linearization is called

    C3 because it is consistent with three properties • a consistent extended precedence graph • preservation of local precedence order • fi tting a monotonicity criterion.
  30. ErSanyamKhurana CuriousLearner C3 Linearization Algorithm The list of the ancestors

    of a class C, including the class itself, ordered from the nearest ancestor to the furthest, is called the class precedence list or the linearization of C.
  31. ErSanyamKhurana CuriousLearner C3 Linearization Algorithm or MRO of class C

    The list of the ancestors of a class C, including the class itself, ordered from the nearest ancestor to the furthest, is called the class precedence list or the linearization of C.
  32. ErSanyamKhurana CuriousLearner How to fi nd MRO in C3 algo?

    The linearization of C is the sum of C plus the merge of the linearizations of the parents and the list of the parents. C B1 B2 BN ...
  33. ErSanyamKhurana CuriousLearner How to fi nd MRO in C3 algo?

    The linearization of C is the sum of C plus the merge of the linearizations of the parents and the list of the parents. L[C(B1 ... BN)] = C + merge(L[B1], ... L[BN], B1 ... BN) C B1 B2 BN ...
  34. ErSanyamKhurana CuriousLearner How to fi nd MRO in C3 algo?

    The linearization of C is the sum of C plus the merge of the linearizations of the parents and the list of the parents. L[C(B1 ... BN)] = C + merge(L[B1], ... L[BN], B1 ... BN) C B1 B2 BN ...
  35. ErSanyamKhurana CuriousLearner How to fi nd MRO in C3 algo?

    The linearization of C is the sum of C plus the merge of the linearizations of the parents and the list of the parents. L[C(B1 ... BN)] = C + merge(L[B1], ... L[BN], B1 ... BN) C B1 B2 BN ...
  36. ErSanyamKhurana CuriousLearner How to fi nd MRO in C3 algo?

    The linearization of C is the sum of C plus the merge of the linearizations of the parents and the list of the parents. L[C(B1 ... BN)] = C + merge(L[B1], ... L[BN], B1 ... BN) C B1 B2 BN ...
  37. ErSanyamKhurana CuriousLearner How to fi nd MRO in C3 algo?

    The linearization of C is the sum of C plus the merge of the linearizations of the parents and the list of the parents. L[C(B1 ... BN)] = C + merge(L[B1], ... L[BN], B1 ... BN) C B1 B2 BN ...
  38. ErSanyamKhurana CuriousLearner How to fi nd MRO in C3 algo?

    L[C(B1 ... BN)] = C + merge(L[B1], ... L[BN], B1 ... BN) Linearization of a class C inheriting from B1 … BN classes will be Class C itself, plus the merge of linearization of all it’s parent classes and the list of parent of classes
  39. ErSanyamKhurana CuriousLearner How to fi nd MRO in C3 algo?

    Linearization of a class C inheriting from B1 … BN classes will be Class C itself, plus the merge of linearization of all it’s parent classes and the list of parent of classes If C is object class, then L[object] = object L[C(B1 ... BN)] = C + merge(L[B1], ... L[BN], B1 ... BN)
  40. ErSanyamKhurana CuriousLearner How to fi nd MRO in C3 algo?

    L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) How to fi nd merge? L[C(B1 ... BN)] = C + merge(L[B1], ... L[BN], B1 ... BN)
  41. ErSanyamKhurana CuriousLearner How to fi nd merge? L[C(B1 ... BN)]

    = C + merge(L[B1] ... L[BN], B1 ... BN) • Take the head of the fi rst list • If the head is not in the tail of any other list, add it to linearization of C and remove it from the lists in merge • Otherwise look at the head of next list to see if it is a good head • Repeat until all classes removed or it is impossible to fi nd good head • Python2.3 will raise an exception in case there are no good heads and will not let you create a class with such a heirarchy
  42. ErSanyamKhurana CuriousLearner How to fi nd merge? L[C(B1 ... BN)]

    = C + merge(L[B1] ... L[BN], B1 ... BN) • Take the head of the fi rst list • If the head is not in the tail of any other list, add it to linearization of C and remove it from the lists in merge • Otherwise look at the head of next list to see if it is a good head • Repeat until all classes removed or it is impossible to fi nd good head • Python2.3 will raise an exception in case there are no good heads and will not let you create a class with such a heirarchy
  43. ErSanyamKhurana CuriousLearner How to fi nd merge? L[C(B1 ... BN)]

    = C + merge(L[B1] ... L[BN], B1 ... BN) • Take the head of the fi rst list • If the head is not in the tail of any other list, add it to linearization of C and remove it from the lists in merge • Otherwise look at the head of next list to see if it is a good head • Repeat until all classes removed or it is impossible to fi nd good head • Python2.3 will raise an exception in case there are no good heads and will not let you create a class with such a heirarchy
  44. ErSanyamKhurana CuriousLearner How to fi nd merge? L[C(B1 ... BN)]

    = C + merge(L[B1] ... L[BN], B1 ... BN) • Take the head of the fi rst list • If the head is not in the tail of any other list, add it to linearization of C and remove it from the lists in merge • Otherwise look at the head of next list to see if it is a good head • Repeat until all classes removed or it is impossible to fi nd good head • Python2.3 will raise an exception in case there are no good heads and will not let you create a class with such a heirarchy
  45. ErSanyamKhurana CuriousLearner How to fi nd merge? L[C(B1 ... BN)]

    = C + merge(L[B1] ... L[BN], B1 ... BN) • Take the head of the fi rst list • If the head is not in the tail of any other list, add it to linearization of C and remove it from the lists in merge • Otherwise look at the head of next list to see if it is a good head • Repeat until all classes removed or it is impossible to fi nd good head • Python2.3 will raise an exception in case there are no good heads and will not let you create a class with such a hierarchy
  46. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[A] = A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN)
  47. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[B] = B + merge(L[A], A) L[B] = B + merge(A, A) L[B] = B A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A
  48. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[B] = B + merge(L[A], A) L[B] = B + merge(A, A) L[B] = B A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A
  49. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[B] = B + merge(L[A], A) L[B] = B + merge(A, A) L[B] = B A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A No Tail here!
  50. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[B] = B + merge(L[A], A) L[B] = B + merge(A, A) L[B] = B A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A
  51. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[C] = C + merge(L[A], A) L[C] = C + merge(A, A) L[C] = C A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A L[B] = B A
  52. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[C] = C + merge(L[A], A) L[C] = C + merge(A, A) L[C] = C A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A L[B] = B A
  53. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[C] = C + merge(L[A], A) L[C] = C + merge(A, A) L[C] = C A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A L[B] = B A
  54. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[C] = C + merge(L[A], A) L[C] = C + merge(A, A) L[C] = C A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A L[B] = B A L[C] = C A
  55. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[D] = D + merge(L[B], L[C], B C) L[D] = D + merge(B A, C A, B C) L[D] = D B + merge(A, C A, C) L[D] = D B C + merge(A, A) L[D] = D B C A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A L[B] = B A L[C] = C A
  56. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[D] = D + merge(L[B], L[C], B C) L[D] = D + merge(B A, C A, B C) L[D] = D B + merge(A, C A, C) L[D] = D B C + merge(A, A) L[D] = D B C A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A L[B] = B A L[C] = C A
  57. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[D] = D + merge(L[B], L[C], B C) L[D] = D + merge(B A, C A, B C) L[D] = D B + merge(A, C A, C) L[D] = D B C + merge(A, A) L[D] = D B C A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A L[B] = B A L[C] = C A
  58. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[D] = D + merge(L[B], L[C], B C) L[D] = D + merge(B A, C A, B C) L[D] = D B + merge(A, C A, C) L[D] = D B C + merge(A, A) L[D] = D B C A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A L[B] = B A L[C] = C A
  59. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[D] = D + merge(L[B], L[C], B C) L[D] = D + merge(B A, C A, B C) L[D] = D B + merge(A, C A, C) L[D] = D B C + merge(A, A) L[D] = D B C A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A L[B] = B A L[C] = C A
  60. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[D] = D + merge(L[B], L[C], B C) L[D] = D + merge(B A, C A, B C) L[D] = D B + merge(A, C A, C) L[D] = D B C + merge(A, A) L[D] = D B C A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A L[B] = B A L[C] = C A
  61. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[D] = D + merge(L[B], L[C], B C) L[D] = D + merge(B A, C A, B C) L[D] = D B + merge(A, C A, C) L[D] = D B C + merge(A, A) L[D] = D B C A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A L[B] = B A L[C] = C A
  62. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[D] = D + merge(L[B], L[C], B C) L[D] = D + merge(B A, C A, B C) L[D] = D B + merge(A, C A, C) L[D] = D B C + merge(A, A) L[D] = D B C A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A L[B] = B A L[C] = C A A is in tail of list, we’ll try to search for next “good” head
  63. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[D] = D + merge(L[B], L[C], B C) L[D] = D + merge(B A, C A, B C) L[D] = D B + merge(A, C A, C) L[D] = D B C + merge(A, A) L[D] = D B C A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A L[B] = B A L[C] = C A
  64. ErSanyamKhurana CuriousLearner L[D] = D + merge(L[B], L[C], B C)

    L[D] = D + merge(B A, C A, B C) L[D] = D B + merge(A, C A, C) L[D] = D B C + merge(A, A) L[D] = D B C A C3 on Diamond Problem A B D C L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A L[B] = B A L[C] = C A No tail here!
  65. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[D] = D + merge(L[B], L[C], B C) L[D] = D + merge(B A, C A, B C) L[D] = D B + merge(A, C A, C) L[D] = D B C + merge(A, A) L[D] = D B C A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A L[B] = B A L[C] = C A
  66. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[D] = D + merge(L[B], L[C], B C) L[D] = D + merge(B A, C A, B C) L[D] = D B + merge(A, C A, C) L[D] = D B C + merge(A, A) L[D] = D B C A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A L[B] = B A L[C] = C A
  67. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[D] = D B C A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A L[B] = B A L[C] = C A
  68. ErSanyamKhurana CuriousLearner C3 on Diamond Problem A B D C

    L[D] = D B C A L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN) L[A] = A L[B] = B A L[C] = C A Note that C3 MRO always traverses parents at same level before going through their ancestors further up the hierarchy
  69. ErSanyamKhurana CuriousLearner C3 on Example 2 L[C] = C +

    merge(L[B], L[A], BA) L[C] = C + merge(B, A, BA) L[C] = C B + merge(A, A) L[C] = C B A A B D C L[A] = A L[B] = B
  70. ErSanyamKhurana CuriousLearner C3 on Example 2 L[C] = C +

    merge(L[B], L[A], BA) L[C] = C + merge(B, A, BA) L[C] = C B + merge(A, A) L[C] = C B A A B D C L[A] = A L[B] = B
  71. ErSanyamKhurana CuriousLearner C3 on Example 2 L[C] = C +

    merge(L[B], L[A], BA) L[C] = C + merge(B, A, BA) L[C] = C B + merge(A, A) L[C] = C B A A B D C L[A] = A L[B] = B
  72. ErSanyamKhurana CuriousLearner C3 on Example 2 L[C] = C +

    merge(L[B], L[A], BA) L[C] = C + merge(B, A, BA) L[C] = C B + merge(A, A) L[C] = C B A A B D C L[A] = A L[B] = B
  73. ErSanyamKhurana CuriousLearner C3 on Example 2 L[D] = D +

    merge(L[B], L[C], B C) L[D] = D + merge(B, C B A, B C) A B D C L[A] = A L[B] = B L[C] = C B A
  74. ErSanyamKhurana CuriousLearner C3 on Example 2 L[D] = D +

    merge(L[B], L[C], B C) L[D] = D + merge(B, C B A, B C) A B D C L[A] = A L[B] = B L[C] = C B A
  75. ErSanyamKhurana CuriousLearner C3 on Example 2 L[D] = D +

    merge(L[B], L[C], B C) L[D] = D + merge(B, C B A, B C) A B D C L[A] = A L[B] = B L[C] = C B A B appears in tail of other list, So, it’s not a good head Let’s move to head of the next list
  76. ErSanyamKhurana CuriousLearner C3 on Example 2 L[D] = D +

    merge(L[B], L[C], B C) L[D] = D + merge(B, C B A, B C) A B D C L[A] = A L[B] = B L[C] = C B A
  77. ErSanyamKhurana CuriousLearner C3 on Example 2 L[D] = D +

    merge(L[B], L[C], B C) L[D] = D + merge(B, C B A, B C) A B D C L[A] = A L[B] = B L[C] = C B A C appears in tail of other list, So, it’s not a good head We’ve exhausted the lists
  78. ErSanyamKhurana CuriousLearner C3 on Example 2 L[D] = D +

    merge(L[B], L[C], B C) L[D] = D + merge(B, C B A, B C) A B D C L[A] = A L[B] = B L[C] = C B A No more good heads 😱
  79. ErSanyamKhurana CuriousLearner C3 on Example 2 L[D] = D +

    merge(L[B], L[C], B C) L[D] = D + merge(B, C B A, B C) A B D C L[A] = A L[B] = B L[C] = C B A Python >= 2.3 raises TypeError 😱
  80. ErSanyamKhurana CuriousLearner C3 on Example 2 L[D] = D +

    merge(L[B], L[C], B C) L[D] = D + merge(B, C B A, B C) A B D C L[A] = A L[B] = B L[C] = C B A Python > 2.3 raises TypeError 😱
  81. ErSanyamKhurana CuriousLearner Python Special Class Attributes 😄 A B D

    C class.__mro__¶ This attribute is a tuple of classes that are considered when looking for base classes during method resolution.
  82. ErSanyamKhurana CuriousLearner Python Special Class Attributes 😄 A B D

    C class.__mro__¶ This attribute is a tuple of classes that are considered when looking for base classes during method resolution.
  83. ErSanyamKhurana CuriousLearner Python Special Class Attributes 😄 A B D

    C class.__bases__ The tuple of base classes of a class object.
  84. ErSanyamKhurana CuriousLearner Python Special Class Attributes 😄 A B D

    C class.__bases__ The tuple of base classes of a class object.
  85. ErSanyamKhurana CuriousLearner Python Special Class Attributes 😄 A B D

    C class.mro() This method can be overridden by a metaclass to customize the method resolution order for its instances. It is called at class instantiation, and its result is stored in __mro__.
  86. ErSanyamKhurana CuriousLearner Python Special Class Attributes 😄 A B D

    C class.mro() This method can be overridden by a metaclass to customize the method resolution order for its instances. It is called at class instantiation, and its result is stored in __mro__.
  87. ErSanyamKhurana CuriousLearner Gotcha 👌 Model fi elds inherited from multiple

    abstract parent models are resolved in a strict depth- fi rst order as opposed to the Python’s MRO.
  88. ErSanyamKhurana CuriousLearner Recap • What is MRO • Old MRO

    / C3 Linearization (New MRO) • History of MRO • Examples on new MRO • TypeError on inconsistent C3 Linearization • Special class attributes related to MRO • MRO in Django
  89. ErSanyamKhurana CuriousLearner Reference • Absolutely amazing explanation on MRO: https://www.python.org/

    download/releases/2.3/mro/ • https://en.wikipedia.org/wiki/C3_linearization