Skip to content

Commit

Permalink
Update formatting and links
Browse files Browse the repository at this point in the history
  • Loading branch information
hugovk committed Mar 6, 2024
1 parent 91e7802 commit aaae147
Showing 1 changed file with 45 additions and 76 deletions.
121 changes: 45 additions & 76 deletions Doc/howto/mro.rst
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
The Python 2.3 Method Resolution Order
======================================

:Version: 1.4
:Author: Michele Simionato
:E-mail: [email protected]
:Address: Department of Physics and Astronomy
210 Allen Hall Pittsburgh PA 15260 U.S.A.
:Home-page: http://www.phyast.pitt.edu/~micheles/
By `Michele Simionato <https://www.phyast.pitt.edu/~micheles/>`__.

:Abstract:

Expand All @@ -18,23 +13,23 @@ The Python 2.3 Method Resolution Order

Disclaimer:

I donate this document to the Python Software Foundation, under the
*I donate this document to the Python Software Foundation, under the
Python 2.3 license. As usual in these circumstances, I warn the
reader that what follows *should* be correct, but I don't give any
warranty. Use it at your own risk and peril!
reader that what follows* should *be correct, but I don't give any
warranty. Use it at your own risk and peril!*

Acknowledgments:

All the people of the Python mailing list who sent me their support.
*All the people of the Python mailing list who sent me their support.
Paul Foley who pointed out various imprecisions and made me to add the
part on local precedence ordering. David Goodger for help with the
formatting in reStructuredText. David Mertz for help with the editing.
Joan G. Stark for the pythonic pictures. Finally, Guido van Rossum who
enthusiastically added this document to the official Python 2.3 home-page.
enthusiastically added this document to the official Python 2.3 home-page.*

----

::
.. code-block:: text
Expand Down Expand Up @@ -127,7 +122,7 @@ which can be represented with the following inheritance graph, where I
have denoted with O the ``object`` class, which is the beginning of any
hierarchy for new style classes:

::
.. code-block:: text
-----------
| |
Expand All @@ -151,7 +146,7 @@ but chooses an *ad hoc* ordering (CABXYO in this case).

----

::
.. code-block:: text
_ .-=-. .-==-.
{ } __ .' O o '. / -<' )
Expand All @@ -165,21 +160,21 @@ The C3 Method Resolution Order
------------------------------

Let me introduce a few simple notations which will be useful for the
following discussion. I will use the shortcut notation
following discussion. I will use the shortcut notation::

C1 C2 ... CN

to indicate the list of classes [C1, C2, ... , CN].

The *head* of the list is its first element:
The *head* of the list is its first element::

head = C1

whereas the *tail* is the rest of the list:
whereas the *tail* is the rest of the list::

tail = C2 ... CN.

I shall also use the notation
I shall also use the notation::

C + (C1 C2 ... CN) = C C1 C2 ... CN

Expand All @@ -195,12 +190,12 @@ following:
*the linearization of C is the sum of C plus the merge of the
linearizations of the parents and the list of the parents.*

In symbolic notation:
In symbolic notation::

L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN)

In particular, if C is the ``object`` class, which has no parents, the
linearization is trivial:
linearization is trivial::

L[object] = object.

Expand All @@ -222,7 +217,7 @@ order cannot be preserved (as in the example of serious order
disagreement discussed above) then the merge cannot be computed.

The computation of the merge is trivial if C has only one parent
(single inheritance); in this case
(single inheritance); in this case::

L[C(B)] = C + merge(L[B],B) = C + L[B]

Expand All @@ -232,7 +227,7 @@ examples ;-)

----

::
.. code-block:: text
.-'-.
/' `\
Expand Down Expand Up @@ -269,9 +264,9 @@ First example. Consider the following hierarchy:
>>> class B(D,E): pass
>>> class A(B,C): pass

In this case the inheritance graph can be drawn as
In this case the inheritance graph can be drawn as:

::
.. code-block:: text
6
---
Expand All @@ -296,43 +291,33 @@ In this case the inheritance graph can be drawn as
---
The linearizations of O,D,E and F are trivial:

::
The linearizations of O,D,E and F are trivial::

L[O] = O
L[D] = D O
L[E] = E O
L[F] = F O

The linearization of B can be computed as

::
The linearization of B can be computed as::

L[B] = B + merge(DO, EO, DE)

We see that D is a good head, therefore we take it and we are reduced to
compute ``merge(O,EO,E)``. Now O is not a good head, since it is in the
tail of the sequence EO. In this case the rule says that we have to
skip to the next sequence. Then we see that E is a good head; we take
it and we are reduced to compute ``merge(O,O)`` which gives O. Therefore

::
it and we are reduced to compute ``merge(O,O)`` which gives O. Therefore::

L[B] = B D E O

Using the same procedure one finds:

::
Using the same procedure one finds::

L[C] = C + merge(DO,FO,DF)
= C + D + merge(O,FO,F)
= C + D + F + merge(O,O)
= C D F O

Now we can compute:

::
Now we can compute::

L[A] = A + merge(BDEO,CDFO,BC)
= A + B + merge(DEO,CDFO,C)
Expand Down Expand Up @@ -360,9 +345,9 @@ my second example:

The only difference with the previous example is the change B(D,E) -->
B(E,D); however even such a little modification completely changes the
ordering of the hierarchy
ordering of the hierarchy:

::
.. code-block:: text
6
---
Expand Down Expand Up @@ -404,7 +389,7 @@ Finally, let me consider the example discussed in the first section,
involving a serious order disagreement. In this case, it is
straightforward to compute the linearizations of O, X, Y, A and B:

::
.. code-block:: text
L[O] = 0
L[X] = X O
Expand All @@ -413,9 +398,7 @@ straightforward to compute the linearizations of O, X, Y, A and B:
L[B] = B Y X O
However, it is impossible to compute the linearization for a class C
that inherits from A and B:

::
that inherits from A and B::

L[C] = C + merge(AXYO, BYXO, AB)
= C + A + merge(XYO, BYXO, B)
Expand All @@ -428,7 +411,7 @@ refuses to create the class C.

----

::
.. code-block:: text
__
(\ .-. .-. /_")
Expand All @@ -453,7 +436,7 @@ following example:

with inheritance diagram

::
.. code-block:: text
O
|
Expand All @@ -476,9 +459,7 @@ gives

This is a breaking of local precedence ordering since the order in the
local precedence list, i.e. the list of the parents of G, is not
preserved in the Python 2.2 linearization of G:

::
preserved in the Python 2.2 linearization of G::

L[G,P22]= G E F object # F *follows* E

Expand All @@ -502,9 +483,7 @@ avoided, since it is unclear if F should override E or viceversa.
Python 2.3 solves the ambiguity by raising an exception in the creation
of class G, effectively stopping the programmer from generating
ambiguous hierarchies. The reason for that is that the C3 algorithm
fails when the merge

::
fails when the merge::

merge(FO,EFO,FE)

Expand All @@ -515,7 +494,7 @@ The real solution is to design a non-ambiguous hierarchy, i.e. to derive
G from E and F (the more specific first) and not from F and E; in this
case the MRO is GEF without any doubt.

::
.. code-block:: text
O
|
Expand Down Expand Up @@ -554,7 +533,7 @@ example:

----

::
.. code-block:: text
__
(\ .-. .-. /_")
Expand All @@ -570,7 +549,7 @@ monotonic.
To prove that the MRO for classic classes is non-monotonic is rather
trivial, it is enough to look at the diamond diagram:

::
.. code-block:: text
C
Expand All @@ -581,17 +560,13 @@ trivial, it is enough to look at the diamond diagram:
\ /
D
One easily discerns the inconsistency:

::
One easily discerns the inconsistency::

L[B,P21] = B C # B precedes C : B's methods win
L[D,P21] = D A C B C # B follows C : C's methods win!

On the other hand, there are no problems with the Python 2.2 and 2.3
MROs, they give both

::
MROs, they give both::

L[D] = D A B C

Expand All @@ -617,9 +592,7 @@ Pedroni, shows that the MRO of Python 2.2 is non-monotonic:

Here are the linearizations according to the C3 MRO (the reader should
verify these linearizations as an exercise and draw the inheritance
diagram ;-)

::
diagram ;-) ::

L[A] = A O
L[B] = B O
Expand All @@ -632,9 +605,7 @@ diagram ;-)
L[Z] = Z K1 K2 K3 D A B C E O

Python 2.2 gives exactly the same linearizations for A, B, C, D, E, K1,
K2 and K3, but a different linearization for Z:

::
K2 and K3, but a different linearization for Z::

L[Z,P22] = Z K1 K3 A K2 D B C E O

Expand All @@ -651,7 +622,7 @@ rule.

----

::
.. code-block:: text
__
(\ .-. .-. .-. .-. .-. .-. .-. .-. /_")
Expand All @@ -672,9 +643,7 @@ inheritance hierarchies ;-) These three virtues taken all together (and
*not* separately) deserve a prize: the prize is a short Python 2.2
script that allows you to compute the 2.3 MRO without risk to your
brain. Simply change the last line to play with the various examples I
have discussed in this paper.

::
have discussed in this paper.::

#<mro.py>

Expand Down Expand Up @@ -765,7 +734,7 @@ That's all folks,

----

::
.. code-block:: text
__
Expand All @@ -778,10 +747,10 @@ Resources
---------

.. [#] The thread on python-dev started by Samuele Pedroni:
http://mail.python.org/pipermail/python-dev/2002-October/029035.html
https://mail.python.org/pipermail/python-dev/2002-October/029035.html
.. [#] The paper *A Monotonic Superclass Linearization for Dylan*:
http://www.webcom.com/haahr/dylan/linearization-oopsla96.html
https://doi.org/10.1145/236337.236343
.. [#] Guido van Rossum's essay, *Unifying types and classes in Python 2.2*:
http://www.python.org/2.2.2/descrintro.html
https://web.archive.org/web/20140210194412/http://www.python.org/download/releases/2.2.2/descrintro

0 comments on commit aaae147

Please sign in to comment.