[Tutor] Inheritance, superclass, ‘super’ (was: __repr__ and __str__)
Ben Finney
ben+python at benfinney.id.au
Wed Jul 1 04:48:47 CEST 2015
Alan Gauld <alan.gauld at btinternet.com> writes:
> Whilst I agree with the general use of super I'm not sure what
> the MRO resolution has to do with this case?
When accessing the superclass, the MRO is always relevant.
> It's explicitly single inheritance and they are explicitly calling the
> superclass.
They don't know that the superclass will be what is written there;
that's an implication of what I said with “in Python, any class an
participate in multiple inheritance”.
The author of a class (e.g. the OP's example ‘MyList’) cannot know at
time of writing whether the superclass is ‘list’. This is because some
other class may be using ‘MyList’ in a different inheritance
arrangement.
Even without either party (the author of ‘MyList’, or the author of the
other class) intending it to be so, the MRO can run through ‘MyList’ in
a direction not specified by either author.
Multiple inheitance is a fact in Python, and good practice is to not
arbitrarily write classes that break it. Hence my advice to avoid
hard-coding the superclass, and only use ‘super’ to discover the
superclass.
> There should be no MRO lookup at this class level (there may be at the
> list level of course).
Much as the class author might like it to be so simple, in Python it
just isn't so: any other class using multiple inheitance may pull in
this one, either as a parent or in some other indirect relationship.
Thus the above assertion is violated.
In Python code it can't be said “there should be not MRO lookup at this
class level”. It's not for the class author to say whether some other
class “should not” inherit, directly or indirectly, from this and some
other class(es).
> super makes sense (sometimes) in a multiple inheritance setup.
Yes, and the class author can't know at time of writing whether that's
the case. So it's prudent to never hard-code the superclass, and to only
use ‘super’ to dynamically determine at run time what is the superclass.
> eg.
>
> class A(B,C,D):
> def m(self):
> C.m(self) # call C's m but not B and D if they have them.
>
> Or am I missing something in the way Python evaluates
> the C.m() call above?
My understanding comes from (among other places) the Python docs::
[…] dynamic ordering is necessary because all cases of multiple
inheritance exhibit one or more diamond relationships (where at
least one of the parent classes can be accessed through multiple
paths from the bottommost class). For example, all new-style classes
inherit from `object`, so any case of multiple inheritance provides
more than one path to reach `object`. […]
<URL:https://docs.python.org/2/tutorial/classes.html>
The paths are determined at run time, and can link through the class one
is writing whether on intends that or not. Any class one writes can
become part of some other class's multiple-inheritance chain, and it is
bad practice to assume one knows at time of writing what the superclass
will be at run time.
We have discused this multiple times in the past. Here is a thread from
2011, explaining why, even one isn't using multiple base classes
explicitly, one should always only ever use ‘super’ to determine at
run-time what the superclass is:
All the smarts managing the entire inheritance hierarchy is built
into `super`, so each method gets called once and exactly once,
provided that every class *only* uses `super`. If you try to mix
`super` calls and direct method calls like B.method(self, arg), it
probably won't work correctly, and if it does, it will probably be
by accident.
So please use `super`, even in single inheritance. Otherwise you are
restricting the usefulness of your class: it can never be used with
multiple inheritance.
<URL:https://mail.python.org/pipermail/tutor/2011-October/086110.html>
Multiple inheritance is a counter-intuitive topic, so it's not really
surprising there is still confusion about it. I try to nip the problem
before it takes hold, by widely advocating use of ‘super’ to aid
everyone else's Python code.
Hope that helps!
--
\ “I took it easy today. I just pretty much layed around in my |
`\ underwear all day. … Got kicked out of quite a few places, |
_o__) though.” —Bug-Eyed Earl, _Red Meat_ |
Ben Finney
More information about the Tutor
mailing list