As you probably know, the multiple inheritance pattern in Python 3 (The new class for Python 2) uses the C3 algorithm to determine the MRO (method Resolution Order).
So how exactly is it calculated? This article will be based on Https://www.python.org/downlo ... A few examples of how MRO is calculated.
Let's start by defining some symbols:
Use CN to denote a class: C1, C2, C3, ..., CN
C1 C2 C3 ... CN represents a list that contains multiple classes [C1, C2, C3, ..., CN]
Among them::
Head = C1
Tail = C2 ... CN
Addition Operation::
C + (C1 C2 ... CN) = C C1 C2 ... CN
[c] + [C1, C2, ..., cn] = [C, C1, C2, ..., CN]
L[c] represents the linear value of Class C, which is actually the MRO of C, where:
L[object] = Object
For example, there is a class:
Class C (B1, B2, ..., BN): Pass
So::
L[c (B1 ... BN)] = C + merge (L[b1] ... L[BN], B1 ... BN)
The merge calculation rules are as follows:
Take the head of the first list, i.e l[b1][0]; If this head isn't in the tail of any of the other lists, then add it to the linearization of C and remove it from the Li STS in the merge, otherwise look at the head of the next list and take it, if it is a good head. Then repeat the operation until all the class is removed or it's impossible to find good heads. In this case, it's impossible to construct the merge, Python 2.3 would refuse to create the class C and would raise an EXCE Ption.
Calculate MRO
Start with a simple class:
Class B (object): Pass
L[B] = L[b (object)]
= B + merge (L[object])
= B + L[object]
= B Object
B.mro ()
[<class 'main. B ';, <type ' object ';]
Simple sub-categories::
Class C (B): Pass
L[C] = L[c (B)]
= C + merge (L[b])
= C + l[b]
= C B Object # already known from above l[b] = b Object
C.mro ()
[<class 'main. C ';, <class 'main. B ';, <type ' object ';]
Let's look at a complex example:
O = Object
Class F (O): Pass
Class E (O): Pass
Class D (O): Pass
Class C (d,f): Pass
Class B (d,e): Pass
Class A (B,C): Pass
It's easy to think:
L[o] = O = Object
L[F] = L[f (o)] = F O
L[e] = L[e (o)] = E O
L[d] = L[d (o)] = D O
The following is a calculation of C, B, A:
L[C]::
L[C] = L[c (D, F)]
= C + merge (L[d], l[f], DF)
# from the previous l[d] and l[f] Results
= C + merge (do, FO, DF)
# because D is the first in order and is head in several lists containing D,
# So this time take D and remove D from the list
= C + D + merge (O, FO, F)
# because O although the first in order but not head in other list (FO), Skip,
# to check the second list FO # F is the head of the second list and other list,
# take F and remove F from the list
= C + D + F + merge (O)
= C D F O
C.mro ()
[<class 'main. C ';, <class 'main. D ';, <class 'main. F ';, <type ' object ';]
L[B]::
L[B] = l[b (D, E)]
= B + merge (L[d], l[e], DE)
= B + merge (do, EO, DE)
= B + D + merge (O, EO, E)
= B + D + E + merge (O)
= B D E O
B.mro ()
[<class 'main. B ';, <class 'main. D ';, <class 'main. E ';, <type ' object ';]
L[a]::
L[a] = L[a (B, C)]
= A + merge (L (B), L (C), BC)
= A + merge (Bdeo, CDFO, BC)
= A + B + merge (DEO, CDFO, C)
# Note that this is C because the head D of the first list is not the head of the other list
# So instead start with the next list CDFO
= A + B + C + merge (DEO, DFO)
= A + B + C + D + merge (EO, FO)
= A + B + C + D + E + merge (O, FO)
= A + B + C + D + E + F + merge (O)
= A B C D E F O
A.mro ()
[<class 'main. A ';, <class 'main. B ';, <class 'main. C ';
<class 'main. D ';, <class 'main. E ';, <class 'main. F ';, <type ' object ';]
There should have been a little bit of a look at it. The next one of the above-mentioned variants of the class, you can calculate the first to see, followed by a detailed calculation process.
O = Object
Class F (O): Pass
Class E (O): Pass
Class D (O): Pass
Class C (d,f): Pass
Class B (e,d): Pass
Class A (B,C): Pass
The only difference is that B (d, E) becomes B (E, D):
L[o] = O = Object
L[f (o)] = F O
L[e (o)] = E O
L[d (o)] = D O
L[C] = L[c (D, F)]
= C + merge (L[d], l[f], DF)
= C D F O
L[B] = l[b (E, D)]
= B + merge (L[e], l[d], ED)
= B + merge (EO, do, ED)
= B + E + merge (O, do, D)
= B + E + D + merge (O)
= B E D O
B.mro ()
[<class 'main. B ';, <class 'main. E ';, <class 'main. D ';, <type ' object ';]
L[a] = L[a (B, C)]
= A + merge (L[b], l[c], BC)
= A + merge (Bedo, CDFO, BC)
= A + B + merge (EDO, CDFO, C)
= A + B + E + merge (do, CDFO, C)
= A + B + E + C + merge (do, DFO)
= A + B + E + C + D + merge (O, FO)
= A + B + E + C + D + F + merge (O)
= A B E C D F O
A.mro ()
[<class 'main. A ';, <class 'main. B ';, <class 'main. E ';
<class 'main. C ';, <class 'main. D ';, <class 'main. F ';, <type ' object ';]
These examples should have some insight into how MRO is calculated, and more detailed information on Python MRO documentation and the C3 algorithm in Wikipedia.
Go-Python: How the MRO (method Resolution Order) is calculated in multi-inheritance mode is related to super