MRO summary description in tutorial still says depth-first
Documentation
Tutorial - Classes chapter - Multiple Inheritance section has a summary description of MRO which still says depth first. That applied to classic Python2 (old) classes.
Linked PRs
- gh-125905
- gh-125906
Providing a PR.
In PR #125906 @erlend-aasland asked "What about the following example in L643-L645?" which is a good point.
Have thought about this more. I had taken the second paragraph in this section as providing a summary description. But maybe should consider the entire section? If "simplest case" means object is the only common parent, and if one ignores object, then the original text is correct for that simplest case.
If the second paragraph is providing a summary description, perhaps that first sentence could read instead:
"For most purposes, you can think of the search for attributes inherited from a parent class as depth-before-common-parent-first, left-to-right, followed by common parents, in a de-duplicated fashion."
Say something like "For exact details, see python_2.3_mro." earlier perhaps before the paragraph starting "In fact, it is slightly more complex than that..."?
Right now I'm inclined to cancel PR #125906 for original or wording that is actually better.
I don't think much belongs in the tutorial other than to say multiple inheritance is available, maybe a summary description, and refer the reader to python_2.3_mro as early as possible. Or have the simple example with only object as common parent and a second example with a common object before parent, like one of the examples from python_2.3_mro.
I don't think much belongs in the tutorial other than to say multiple inheritance is available, maybe a summary description, and refer the reader to python_2.3_mro as early as possible. Or have the simple example with only object as common parent and a second example with a common object before parent, like one of the examples from python_2.3_mro.
I agree that nitty gritty details about the MRO does not necessarily need to be a part of the tutorial. A .. seealso that points to an explanatory section sounds like an improvement to me.
But maybe should consider the entire section?
Yes, I think one should consider the entire section.
Hi there. Just spotted this issue in documentation. Here is code, I've used to understand that something is wrong.
class P1:
def who_am_i(self):
print("I am P1")
def extra(self):
print("I am P1.extra")
class P2a(P1):
def who_am_i(self):
print("I am P2a & calling extra")
self.extra()
class P2b(P1):
def who_am_i(self):
print("I am P2b")
def extra(self):
print("I am P2b.extra")
class P3(P2a, P2b):
pass
P3().extra() # prints "I am P2b.extra"
P3().who_am_i() # prints "I am P1a" and "I am P2b.extra"
And here is explanation from AI.
In Python, method resolution order (MRO) for multiple inheritance uses the C3 linearization algorithm, not simple depth-first search. This means Python looks for methods in a specific order that combines the inheritance hierarchy and the order of base classes.
For your example:
The MRO for [P3] is:
[P3 → P2a → P2b → P1 → object]
When you call [P3().extra()], Python searches for `extra` in this order:
[P3] (no [extra])
[P2a] (no [extra])
[P2b] (has [extra]) ← found here, so it prints "I am P2b.extra"
[P1] (not reached)
Summary:
Python does not use depth-first search for method lookup. It uses the MRO, which in this case finds [extra] in [P2b] before [P1]. That's why "I am P2b.extra" is printed.
I've found explanation very clear. Maybe it will help you to fix documentation