Before you can read the parent note, you need to see what a class is, what "inherit" means as a picture, what a list and its head/tail are, and what an "order" even is. This page builds every one of those from nothing.
Picture a rubber stamp. The stamp is the class; every ink mark it leaves on paper is an instance. The shape carved into the stamp — the lines it will print — is the set of methods and attributes.
Figure s01 — On the left, a single blue box labelled "class (stamp)". Yellow arrows fan out to three small green boxes labelled "instance #1, #2, #3". The picture says: one blueprint produces many stamped copies. Look at how every arrow starts from the same stamp — that shared origin is the class.
A method is just a function that lives inside a class. When you write d.speak(), Python must find a method named speak somewhere. Where it looks — and in what order — is the entire subject of Method Resolution Order.
The picture is an arrow pointing from child up to parent. Read the arrow as "is a kind of": a Dogis a kind ofAnimal.
Figure s02 — A green box "Dog (child)" sits at the bottom; a blue box "Animal (parent)" sits above it. A red arrow points UP from Dog to Animal, labelled 'is a kind of'. The yellow caption reminds you that a search starts at Dog and only climbs the arrow to Animal if Dog itself lacks the method. Notice the arrow points from child to parent, but the search travels the same direction only after checking the child first.
Picture the top of a family tree: no matter which cousin you start from, all the branches eventually meet at one shared ancestor. That shared ancestor is O. Because it is everyone's parent, the golden rule (child before parent) forces O to always sit last in any search order.
If B and C both point up to the same A, the four arrows form a diamond:
A
/ \
B C
\ /
D
Figure s03 — The classic diamond: blue box A on top, two green boxes B and C in the middle, yellow box D at the bottom. Red arrows show D reaching A by two separate roads (labelled "road 1" through B and "road 2" through C). The whole problem of this topic lives in this picture: two roads to A means we must decide when to place A so we neither visit it twice nor visit it too early.
The algorithm works entirely on lists of classes, so you must be fluent in three words. (Now that O means the root class, the sample list [B,A,O] below reads as "first B, then A, then object.")
For the list [B,A,O]:
head =B
tail =[A,O] ← note: AandO are both "in the tail".
Figure s04 — The list [B, A, O] drawn as three boxes in a row. A yellow arrow points down to the first box marked "HEAD". A red bracket underlines the remaining two boxes marked "TAIL = everything after the head". The lesson to read off the picture: only the tail (red) blocks a candidate; the head slot (yellow) is exactly where we want the next class to come from.
Picture sliding one new box into the leftmost slot of a row of boxes, pushing nothing else around — they all just shift one place right. That single leftmost box is now the head; everything you had before becomes the tail.
Before the abstract formula, let us weave three lists into one by hand so the head/tail rule becomes concrete. This is the merge from the diamond class D(B, C) where B(A) and C(A). We already know the parents' orders: L[B]=[B,A,O], L[C]=[C,A,O], and the plain parent list is [B,C].
Figure s05 — Four horizontal rows, one per merge step, showing the three lists shrinking left-to-right. In each row the class being emitted is circled in green and struck out of every list; a red X marks any candidate rejected because it sits in a tail. Reading top to bottom you literally watch the diamond flatten into the single green line D, B, C, A, O at the bottom — this is the "weaving" the diamond picture only hinted at.
We start with these three lists (D itself is already placed out front):
merge([B,A,O],[C,A,O],[B,C])
Putting D back in front with the prepend operator: L[D]=D+[B,C,A,O]=[D,B,C,A,O]. The diamond became one clean line, A appears exactly once, and it lands after both B and C — precisely the child-before-parent rule paying off.
Turning a branching shape (the diamond) into one straight line while obeying constraints is exactly a Topological sort — an ordering that respects "this must come before that" arrows. C3 is a topological sort with two extra tie-breaking rules (keep written parent order; stay monotonic).
You wrote class D(B, C), so in any tie between B and C, B must win — because you listed it first. Watch it happen in Step 1 above: both B and C were sitting at the front of some list, but the merge always tests list 1 first (which starts with B, the first-written parent). That is why the output is […B,C…] and never […C,B…]. The plain parent list [B,C] at the end of the formula is the guardrail that enforces this: if the merge ever tried to emit C before B, then C would be blocked because B is still in the tail of [B,C].
Monotonicity means an order, once established in a parent, is never flipped in a child. In L[B]=[B,A,O], B comes before A. Any subclass of B — including D — must keep B before A. Check the final answer [D,B,C,A,O]: yes, B still precedes A.
Why does flipping break things? Suppose some algorithm produced [D,A,B,…] — putting the parent Abefore its child B. Then calling a method that B overrides would find A's old version first. The child's improvement would be silently ignored. Monotonicity is the promise that this never happens: refinements always stay in front of what they refine.
The parent page hands you the formula finished. Here is why each piece is there, assembled from scratch.
Piece 1 — "C+". A child is always searched before its parents, so the line must start with C itself, glued on with the prepend operator we defined in Section 4. That is the leading C +.
Piece 2 — "the parents' own orders." Each parent Pi already knows how it wants its ancestors ordered: that is L[Pi]. If we ignored these we could contradict a parent's internal order (breaking monotonicity). So we must feed everyL[P1],…,L[Pn] into the weave.
Piece 3 — "the plain list [P1,…,Pn]". Why one more list? The parents' individual orders don't say anything about how the parents rank against each other. Without a tiebreaker the merge could emit C's parents in the wrong order. Adding the raw written order [P1,…,Pn] forces local precedence: it keeps B ahead of C because in that list C sits in the tail behind B. This is the exact guardrail we saw in the local-precedence example.
Weaving all three pieces with the head/tail merge gives:
Every symbol here you have now met: C (a class), Pi (its parents), L[⋅] (an order), + (front-prepend), merge (the weaver), O (the root). The topic uses no notation beyond these.
Let us run the formula end-to-end on the simplest possible case, class B: pass then class A(B): pass, so you see the base case and merge cooperate without any diamond.
Sometimes the constraints genuinely contradict each other and no valid line exists. C3 must detect this and refuse, rather than invent a wrong order.
Concretely, imagine the merge has reduced to two lists [X,Y,O] and [Y,X,O]. Test the head of list 1, X: it sits in the tail of list 2 (which is [X,O]) → blocked. Test the head of list 2, Y: it sits in the tail of list 1 (which is [Y,O]) → blocked. Both heads are blocked, no list remains to try — deadlock detected, so C3 raises the TypeError.
Picture the deadlock: X is waiting behind Y in one list, and Y is waiting behind X in another. Each is politely holding the door for the other, forever. That standstill is exactly the "no good head" state, and detecting it is C3's built-in safety check.