I'm reading Python 2.3 MRO article, where the following class hierarchy is given:
>>> 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
6
---
Level 3 | O |
/ --- \
/ | \
/ | \
/ | \
--- --- ---
Level 2 2 | E | 4 | D | | F | 5
--- --- ---
\ / \ /
\ / \ /
\ / \ /
--- ---
Level 1 1 | B | | C | 3
--- ---
\ /
\ /
---
Level 0 0 | A |
---
On the paragraph following it, the following quote left me confused:
A lazy programmer can obtain the MRO directly from Python 2.2, since in this case it coincides with the Python 2.3 linearization.
>>> A.mro() (<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.F'>, <type 'object'>)
The reason I'm confused is that earlier on the article it's stated:
Classic classes maintain their old method resolution order, depth first and then left to right.
Question: If the old-style MRO is depth-first, left to right, then the old-style MRO of the aforementioned class hierarchy should be different, i.e ABEODOCDOFO. Therefore, the "lazy programmer" cannot obtain its MRO directly from Python 2.2. Is that right?
For example, on the following snippet (Don't run it on Python 3.x):
class O:
x = 'o'
class F(O): pass
class E(O): pass
class D(O): pass
class C(D,F):
x = 'c'
class B(E,D): pass
class A(B,C): pass
print A.x
If the old-style MRO was the same as the new-style MRO (i.e., ABEC etc.), I'd expect it to print c
. However, it prints o
(i.e., it's ABEO etc.).
Or here:
class O: pass
class F(O): pass
class E(O): pass
class D(O):
x = 'd'
class C(D,F):
x = 'c'
class B(E,D): pass
class A(B,C): pass
print A.x
If the old-style MRO was the same as the new-style MRO (i.e., ABEC etc.), I'd expect it to print c
. However, it prints d
(i.e., it's ABEOD etc.).
I'm new to Python, so I guess I miss something?
The thing is, whether in Python 2.2, 2.3, or later, these are all new-style classes. There are 3 method resolution schemes here, not 2:
Schemes 2 and 3 would produce the same MRO for the given example.
If you want to see the (now almost completely irrelevant) Python 2.2 method resolution scheme, the most complete documentation is probably a blog post from Guido's old Python history blog. There's also an old archived draft of documentation for Python 2.2, which mostly describes it but fails to mention a special case.